0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

書籍 ダイテル C言語プログラミング 練習問題 解答 7章

0
Last updated at Posted at 2026-03-30
書籍

image.png

7.12: リスト7.14(P269)のプログラムにあるカード分配関数を5枚配った時点でポーカーの手(役)を判定できるよう変更したプログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void shuffle(int [][13]);
void deal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

// 「5枚」のカードの役を判定する関数
int CheckPost(int [], int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   shuffle(deck);
   deal(deck, face, suit);

   return 0;
}

void shuffle(int wDeck[][13])
{
   int card, row, column;

   for (card = 1; card <= 52; card++)
   {
       row = rand() % 4;
       column = rand() % 13;

       while (wDeck[row][column] != 0)
       {
           row = rand() % 4;
           column = rand() % 13;
       }
 
       wDeck[row][column] = card;
   }
}

void deal(int wDeck[][13], const char *wFace[], const char *wSuit[])
{
   int card, row, column;
   int next = 0;
   int checkRow[5]; // 5枚目までのカードの柄を順に記録する配列 1P
   int checkCol[5]; // 5枚目までのカードの数字を順に記録する配列 1P
   int a;

   for (card = 1; card <= 52; card++)
   {
       for (row = 0; row <= 3; row++)
       {
          for (column = 0; column <= 12; column++)
          {
              if (wDeck[row][column] == card)
              {
                 printf("%8s の %-8s%c", wSuit[row], wFace[column],
                        card % 2 == 0 ? '\n' : '\t');

                 // 5枚目までは1P用
                 if (next < 5)
                 {
                    checkRow[next] = row;
                    checkCol[next] = column;
                    next++;

                    if (next == 5)
                    {
                        a = CheckPost(checkRow, checkCol);
                        printf("The result of the hand judgement is %d\n", a);
                        return; // ← ここで処理を終了
                    }

                 }
              }
          }
       }
   }
}

// 「5枚」のカードの役を判定する関数
// 戻り値 6-1:役の強さ 0:役ができてない
int CheckPost(int checkRow[], int checkCol[])
{
           // ストレートがあるかを調べる
           if (CheckStraight(checkCol) == 1)
           {
               return 6;
           }

           // フラッシュがあるかを調べる
           if (CheckFlush(checkRow) == 1)
           {
               return 5;
           }

           // フォーカードがあるかを調べる
           if (CheckFourCard(checkCol) == 1)
           {
               return 4;
           }

           // スリーカードがあるかを調べる
           if (CheckThreeCard(checkCol) == 1)
           {
               return 3;
           }

           // ツーペアがあるかを調べる
           if (CheckTwoPair(checkCol) == 1)
           {
               return 2;
           }

            // ワンペアがあるかを調べる
           if (CheckOnePair(checkCol) == 1)
           {
               return 1;
           }  
 
           // 役がそろってないならば
           return 0;
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) return 1;
    }
    return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    int count[13] = {0}, pair = 0;
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) pair++;
    }
    return (pair == 2);
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 3) return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 4) return 1;
    }
    return 0;
}

// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    for (int i = 0; i < 5; i++) {
        if (checkRow[i] != checkRow[0]) return 0;
    }
    return 1;
}

// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.13: 2人のプレイヤーにカードを5枚ずつ配り、両者がもっているポーカーの手を評価して、どちらの手が勝っているかを判定するプログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void shuffle(int [][13]);
void deal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

// 「5枚」のカードの役を判定する関数
int CheckPost(int [], int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   shuffle(deck);
   deal(deck, face, suit);

   return 0;
}

void shuffle(int wDeck[][13])
{
   int card, row, column;

   for (card = 1; card <= 52; card++)
   {
       row = rand() % 4;
       column = rand() % 13;

       while (wDeck[row][column] != 0)
       {
           row = rand() % 4;
           column = rand() % 13;
       }
 
       wDeck[row][column] = card;
   }
}

void deal(int wDeck[][13], const char *wFace[], const char *wSuit[])
{
    int card, row, column;
    int next = 0;
    int checkRow[5], checkCol[5];     // 1Pのカード
    int checkRow1[5], checkCol1[5];   // 2Pのカード
    int a = -1, b = -1;

    printf("【1Pのカード】\n");

    for (card = 1; card <= 52; card++)
    {
        for (row = 0; row < 4; row++)
        {
            for (column = 0; column < 13; column++)
            {
                if (wDeck[row][column] == card)
                {
                    if (next < 5)
                    {
                        printf("%8s の %-8s%c", wSuit[row], wFace[column],
                               next % 2 == 1 ? '\n' : '\t');

                        checkRow[next] = row;
                        checkCol[next] = column;
                    }
                    else if (next == 5)
                    {
                        printf("\n【2Pのカード】\n");
                    }

                    if (next >= 5 && next < 10)
                    {
                        printf("%8s の %-8s%c", wSuit[row], wFace[column],
                               next % 2 == 1 ? '\n' : '\t');

                        checkRow1[next - 5] = row;
                        checkCol1[next - 5] = column;
                    }

                    next++;

                    if (next == 10)
                    {
                        a = CheckPost(checkRow, checkCol);
                        b = CheckPost(checkRow1, checkCol1);

                        printf("\n【役判定結果】\n");
                        printf("1P の役: %d\n", a);
                        printf("2P の役: %d\n", b);

                        if (a > b)
                            printf("→ 1Pの勝ちです!\n");
                        else if (a < b)
                            printf("→ 2Pの勝ちです!\n");
                        else
                            printf("→ 引き分けです!\n");

                        return;
                    }
                }
            }
        }
    }
}

// 「5枚」のカードの役を判定する関数
// 戻り値 6-1:役の強さ 0:役ができてない
int CheckPost(int checkRow[], int checkCol[])
{
           // ストレートがあるかを調べる
           if (CheckStraight(checkCol) == 1)
           {
               return 6;
           }

           // フラッシュがあるかを調べる
           if (CheckFlush(checkRow) == 1)
           {
               return 5;
           }

           // フォーカードがあるかを調べる
           if (CheckFourCard(checkCol) == 1)
           {
               return 4;
           }

           // スリーカードがあるかを調べる
           if (CheckThreeCard(checkCol) == 1)
           {
               return 3;
           }

           // ツーペアがあるかを調べる
           if (CheckTwoPair(checkCol) == 1)
           {
               return 2;
           }

            // ワンペアがあるかを調べる
           if (CheckOnePair(checkCol) == 1)
           {
               return 1;
           }  
 
           // 役がそろってないならば
           return 0;
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) return 1;
    }
    return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    int count[13] = {0}, pair = 0;
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) pair++;
    }
    return (pair == 2);
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 3) return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 4) return 1;
    }
    return 0;
}



// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    for (int i = 0; i < 5; i++) {
        if (checkRow[i] != checkRow[0]) return 0;
    }
    return 1;
}


// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.14: 7.13で開発したプログラムをディーラーをシミュレートできるよう変更したプログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void shuffle(int [][13]);
void deal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

// 「5枚」のカードの役を判定する関数
int CheckPost(int [], int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   shuffle(deck);
   deal(deck, face, suit);

   return 0;
}

void shuffle(int wDeck[][13])
{
   int card, row, column;

   for (card = 1; card <= 52; card++)
   {
       row = rand() % 4;
       column = rand() % 13;

       while (wDeck[row][column] != 0)
       {
           row = rand() % 4;
           column = rand() % 13;
       }
 
       wDeck[row][column] = card;
   }
}

void deal(int wDeck[][13], const char *wFace[], const char *wSuit[])
{
    int card, row, column;
    int next = 0;
    int playerRow[5], playerCol[5];   // プレイヤーのカード
    int dealerRow[5], dealerCol[5];   // ディーラーのカード
    int a = -1, b = -1;

    printf("【プレイヤーのカード】\n");

    for (card = 1; card <= 52; card++)
    {
        for (row = 0; row < 4; row++)
        {
            for (column = 0; column < 13; column++)
            {
                if (wDeck[row][column] == card)
                {
                    if (next < 5)
                    {
                        printf("%8s の %-8s%c", wSuit[row], wFace[column],
                               next % 2 == 1 ? '\n' : '\t');

                        playerRow[next] = row;
                        playerCol[next] = column;
                    }
                    else if (next >= 5 && next < 10)
                    {
                        dealerRow[next - 5] = row;
                        dealerCol[next - 5] = column;
                    }

                    next++;

                    if (next == 10)
                    {
                        a = CheckPost(playerRow, playerCol);
                        b = CheckPost(dealerRow, dealerCol);

                        // ディーラーの手札を評価して不要なカードを捨てる
                        int discard[5] = {0}; // 捨てるかどうかのフラグ
                        int count[13] = {0};
                        for (int i = 0; i < 5; i++) count[dealerCol[i]]++;
                         
                        // 役に関係ないカードを捨てる判定
                        for (int i = 0; i < 5; i++) {
                            if (count[dealerCol[i]] == 1) discard[i] = 1;
                        }

                        // 最大3枚まで交換
                        int discardCount = 0;
                        int drawCard = card + 1;

                        for (int i = 0; i < 5 && discardCount < 3; i++) {
                            if (discard[i]) {
                                int found = 0;
                                while (drawCard <= 52 && !found) {
                                    for (int r2 = 0; r2 < 4 && !found; r2++) {
                                        for (int c2 = 0; c2 < 13 && !found; c2++) {
                                            if (wDeck[r2][c2] == drawCard) {
                                                dealerRow[i] = r2;
                                                dealerCol[i] = c2;
                                                drawCard++;
                                                discardCount++;
                                                found = 1;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // 再評価
                        b = CheckPost(dealerRow, dealerCol);

                        printf("\n【役判定結果】\n");
                        printf("プレイヤーの役: %d\n", a);
                        printf("ディーラーの役: %d(伏せ札)\n", b);

                        if (a > b)
                            printf("→ プレイヤーの勝ちです!\n");
                        else if (a < b)
                            printf("→ ディーラーの勝ちです!\n");
                        else
                            printf("→ 引き分けです!\n");

                        return;
                    }
                }
            }
        }
    }
}

// 「5枚」のカードの役を判定する関数
// 戻り値 6-1:役の強さ 0:役ができてない
int CheckPost(int checkRow[], int checkCol[])
{
           // ストレートがあるかを調べる
           if (CheckStraight(checkCol) == 1)
           {
               return 6;
           }

           // フラッシュがあるかを調べる
           if (CheckFlush(checkRow) == 1)
           {
               return 5;
           }

           // フォーカードがあるかを調べる
           if (CheckFourCard(checkCol) == 1)
           {
               return 4;
           }

           // スリーカードがあるかを調べる
           if (CheckThreeCard(checkCol) == 1)
           {
               return 3;
           }

           // ツーペアがあるかを調べる
           if (CheckTwoPair(checkCol) == 1)
           {
               return 2;
           }

            // ワンペアがあるかを調べる
           if (CheckOnePair(checkCol) == 1)
           {
               return 1;
           }  
 
           // 役がそろってないならば
           return 0;
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) return 1;
    }
    return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    int count[13] = {0}, pair = 0;
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) pair++;
    }
    return (pair == 2);
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 3) return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 4) return 1;
    }
    return 0;
}



// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    for (int i = 0; i < 5; i++) {
        if (checkRow[i] != checkRow[0]) return 0;
    }
    return 1;
}


// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.15: 7.14で開発したプログラムをディーラーの役目を自動的に果たすように変更したプログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

void shuffle(int [][13]);
void deal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

// 「5枚」のカードの役を判定する関数
int CheckPost(int [], int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   shuffle(deck);
   deal(deck, face, suit);

   return 0;
}

void shuffle(int wDeck[][13])
{
   int card, row, column;

   for (card = 1; card <= 52; card++)
   {
       row = rand() % 4;
       column = rand() % 13;

       while (wDeck[row][column] != 0)
       {
           row = rand() % 4;
           column = rand() % 13;
       }
 
       wDeck[row][column] = card;
   }
}

void DealerExchange(int wDeck[][13], int dealerRow[], int dealerCol[], int usedCard)
{
    int rank = CheckPost(dealerRow, dealerCol);
    int discard[5] = {0};
    int count[13] = {0};

    for (int i = 0; i < 5; i++) count[dealerCol[i]]++;

    int discardCount = 0;

    if (rank == 4) { // フォーカード → 1枚交換
        for (int i = 0; i < 5; i++) {
            if (count[dealerCol[i]] == 1) {
                discard[i] = 1;
                discardCount++;
                break;
            }
        }
    } else if (rank == 3 || rank == 2) { // スリーカード or ツーペア → 1〜2枚交換
        for (int i = 0; i < 5 && discardCount < 2; i++) {
            if (count[dealerCol[i]] == 1) {
                discard[i] = 1;
                discardCount++;
            }
        }
    } else if (rank == 1 || rank == 0) { // ワンペア or 役なし → 最大3枚交換
        for (int i = 0; i < 5 && discardCount < 3; i++) {
            if (count[dealerCol[i]] == 1) {
                discard[i] = 1;
                discardCount++;
            }
        }
    }

    int drawCard = usedCard + 1;
    for (int i = 0; i < 5; i++) {
        if (discard[i]) {
            int found = 0;
            while (drawCard <= 52 && !found) {
                for (int r2 = 0; r2 < 4 && !found; r2++) {
                    for (int c2 = 0; c2 < 13 && !found; c2++) {
                        if (wDeck[r2][c2] == drawCard) {
                            dealerRow[i] = r2;
                            dealerCol[i] = c2;
                            drawCard++;
                            found = 1;
                        }
                    }
                }
            }
        }
    }
}

void deal(int wDeck[][13], const char *wFace[], const char *wSuit[])
{
    int card, row, column;
    int next = 0;
    int playerRow[5], playerCol[5];
    int dealerRow[5], dealerCol[5];
    int a = -1, b = -1;

    printf("【プレイヤーのカード】\n");

    for (card = 1; card <= 52; card++) {
        for (row = 0; row < 4; row++) {
            for (column = 0; column < 13; column++) {
                if (wDeck[row][column] == card) {
                    if (next < 5) {
                        printf("%d: %8s の %-8s%c", next, wSuit[row], wFace[column],
                               next % 2 == 1 ? '\n' : '\t');
                        playerRow[next] = row;
                        playerCol[next] = column;
                    } else if (next >= 5 && next < 10) {
                        dealerRow[next - 5] = row;
                        dealerCol[next - 5] = column;
                    }

                    next++;

                    if (next == 10) {
                        // プレイヤーの捨て札選択
                        int discard[5] = {0};
                        int discardCount = 0;
                        printf("\n捨てたいカードの位置(0〜4)を入力(例: 0 2 4): ");
                        char input[100];
                        fgets(input, sizeof(input), stdin);
                        int idx;
                        char *token = strtok(input, " ");
                        while (token != NULL && discardCount < 3) {
                            if (sscanf(token, "%d", &idx) == 1 && idx >= 0 && idx < 5 && discard[idx] == 0) {
                                discard[idx] = 1;
                                discardCount++;
                            }
                            token = strtok(NULL, " ");
                        }

                        int drawCard = card + 1;
                        for (int i = 0; i < 5; i++) {
                            if (discard[i]) {
                                int found = 0;
                                while (drawCard <= 52 && !found) {
                                    for (int r2 = 0; r2 < 4 && !found; r2++) {
                                        for (int c2 = 0; c2 < 13 && !found; c2++) {
                                            if (wDeck[r2][c2] == drawCard) {
                                                playerRow[i] = r2;
                                                playerCol[i] = c2;
                                                drawCard++;
                                                found = 1;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // ディーラーの自動交換
                        int dealerDiscard[5] = {0};
                        int count[13] = {0};
                        for (int i = 0; i < 5; i++) count[dealerCol[i]]++;
                        for (int i = 0; i < 5; i++) {
                            if (count[dealerCol[i]] == 1) dealerDiscard[i] = 1;
                        }

                        int dealerDraw = drawCard;
                        int dealerDiscardCount = 0;
                        for (int i = 0; i < 5 && dealerDiscardCount < 3; i++) {
                            if (dealerDiscard[i]) {
                                int found = 0;
                                while (dealerDraw <= 52 && !found) {
                                    for (int r2 = 0; r2 < 4 && !found; r2++) {
                                        for (int c2 = 0; c2 < 13 && !found; c2++) {
                                            if (wDeck[r2][c2] == dealerDraw) {
                                                dealerRow[i] = r2;
                                                dealerCol[i] = c2;
                                                dealerDraw++;
                                                dealerDiscardCount++;
                                                found = 1;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // 役判定
                        a = CheckPost(playerRow, playerCol);
                        DealerExchange(wDeck, dealerRow, dealerCol, card);
                        b = CheckPost(dealerRow, dealerCol);

                        printf("\n【役判定結果】\n");
                        printf("プレイヤーの役: %d\n", a);
                        printf("ディーラーの役: %d(伏せ札)\n", b);

                        if (a > b)
                            printf("→ プレイヤーの勝ちです!\n");
                        else if (a < b)
                            printf("→ ディーラーの勝ちです!\n");
                        else
                            printf("→ 引き分けです!\n");

                        return;
                    }
                }
            }
        }
    }
}

// 「5枚」のカードの役を判定する関数
// 戻り値 6-1:役の強さ 0:役ができてない
int CheckPost(int checkRow[], int checkCol[])
{
           // ストレートがあるかを調べる
           if (CheckStraight(checkCol) == 1)
           {
               return 6;
           }

           // フラッシュがあるかを調べる
           if (CheckFlush(checkRow) == 1)
           {
               return 5;
           }

           // フォーカードがあるかを調べる
           if (CheckFourCard(checkCol) == 1)
           {
               return 4;
           }

           // スリーカードがあるかを調べる
           if (CheckThreeCard(checkCol) == 1)
           {
               return 3;
           }

           // ツーペアがあるかを調べる
           if (CheckTwoPair(checkCol) == 1)
           {
               return 2;
           }

            // ワンペアがあるかを調べる
           if (CheckOnePair(checkCol) == 1)
           {
               return 1;
           }  
 
           // 役がそろってないならば
           return 0;
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) return 1;
    }
    return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    int count[13] = {0}, pair = 0;
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) pair++;
    }
    return (pair == 2);
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 3) return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 4) return 1;
    }
    return 0;
}



// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    for (int i = 0; i < 5; i++) {
        if (checkRow[i] != checkRow[0]) return 0;
    }
    return 1;
}


// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.16: 不定延期(無駄な操作を何度も繰り返すこと)の可能性をもつ非効率な混合アルゴリズムを回避する効率のよい混合アルゴリズムを実装したカード混合・分配プログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

void shuffle(int [][13]);
void deal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

// 「5枚」のカードの役を判定する関数
int CheckPost(int [], int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   shuffle(deck);
   deal(deck, face, suit);

   return 0;
}

// カード番号 card の位置を deck 配列から探して row, col に格納する
void findCard(int deck[4][13], int card, int *row, int *col)
{
    for (int r = 0; r < 4; r++) {
        for (int c = 0; c < 13; c++) {
            if (deck[r][c] == card) {
                *row = r;
                *col = c;
                return; // 見つかったら即座に抜ける
            }
        }
    }
}

void shuffle(int deck[4][13]) {
    // 初期化:1〜52のカード番号を順に配置
    for (int row = 0; row < 4; row++) {
        for (int col = 0; col < 13; col++) {
            deck[row][col] = row * 13 + col + 1;
        }
    }

    // シャッフル:各要素を1回ずつ見ながらランダムな位置と交換
    for (int row = 0; row < 4; row++) {
        for (int col = 0; col < 13; col++) {
            int randRow = rand() % 4;
            int randCol = rand() % 13;

            // 交換
            int temp = deck[row][col];
            deck[row][col] = deck[randRow][randCol];
            deck[randRow][randCol] = temp;
        }
    }

    // シャッフル後の配列を表示
    printf("【シャッフル後のdeck配列】\n");
    for (int row = 0; row < 4; row++) {
        for (int col = 0; col < 13; col++) {
            printf("%3d ", deck[row][col]);
        }
        printf("\n");
    }
}

void deal(int deck[4][13], const char *face[], const char *suit[])
{
    int playerRow[5], playerCol[5];
    int dealerRow[5], dealerCol[5];
    int card = 1, next = 0;

    printf("【プレイヤーのカード】\n");

    while (card <= 52 && next < 10) {
        int r, c;
        findCard(deck, card, &r, &c);

        if (next < 5) {
            printf("%d: %8s の %-8s%c", next, suit[r], face[c],
                   next % 2 == 1 ? '\n' : '\t');
            playerRow[next] = r;
            playerCol[next] = c;
        } else {
            dealerRow[next - 5] = r;
            dealerCol[next - 5] = c;
        }

        next++;
        card++;
    }

    // プレイヤーの交換
    int discard[5] = {0}, discardCount = 0;
    printf("\n捨てたいカードの位置(0~4)を最大3枚まで入力(例: 0 2 4): ");
    char input[100];
    fgets(input, sizeof(input), stdin);
    int idx;
    char *token = strtok(input, " ");
    while (token != NULL && discardCount < 3) {
        if (sscanf(token, "%d", &idx) == 1 && idx >= 0 && idx < 5 && discard[idx] == 0) {
            discard[idx] = 1;
            discardCount++;
        }
        token = strtok(NULL, " ");
    }

    for (int i = 0; i < 5; i++) {
        if (discard[i]) {
            int r, c;
            findCard(deck, card++, &r, &c);
            playerRow[i] = r;
            playerCol[i] = c;
        }
    }

    // ディーラーの交換(強化版)
    int rank = CheckPost(dealerRow, dealerCol);
    int count[13] = {0}, dealerDiscard[5] = {0}, dealerDiscardCount = 0;
    for (int i = 0; i < 5; i++) count[dealerCol[i]]++;

    // rank が 2 以上(ツーペア以上)なら → 最大2枚まで交換
    int maxDiscard = (rank >= 4) ? 1 : (rank >= 2) ? 2 : 3;
    for (int i = 0; i < 5 && dealerDiscardCount < maxDiscard; i++) {
        if (count[dealerCol[i]] == 1) {
            dealerDiscard[i] = 1;
            dealerDiscardCount++;
        }
    }

    for (int i = 0; i < 5; i++) {
        if (dealerDiscard[i]) {
            int r, c;
            findCard(deck, card++, &r, &c);
            dealerRow[i] = r;
            dealerCol[i] = c;
        }
    }

    // 役判定と勝敗表示
    int a = CheckPost(playerRow, playerCol);
    int b = CheckPost(dealerRow, dealerCol);

    printf("\n【役判定結果】\n");
    printf("プレイヤーの役: %d\n", a);
    printf("ディーラーの役: %d(伏せ札)\n", b);

    if (a > b)
        printf("→ プレイヤーの勝ちです!\n");
    else if (a < b)
        printf("→ ディーラーの勝ちです!\n");
    else
        printf("→ 引き分けです!\n");
}

// 「5枚」のカードの役を判定する関数
// 戻り値 6-1:役の強さ 0:役ができてない
int CheckPost(int checkRow[], int checkCol[])
{
           // ストレートがあるかを調べる
           if (CheckStraight(checkCol) == 1)
           {
               return 6;
           }

           // フラッシュがあるかを調べる
           if (CheckFlush(checkRow) == 1)
           {
               return 5;
           }

           // フォーカードがあるかを調べる
           if (CheckFourCard(checkCol) == 1)
           {
               return 4;
           }

           // スリーカードがあるかを調べる
           if (CheckThreeCard(checkCol) == 1)
           {
               return 3;
           }

           // ツーペアがあるかを調べる
           if (CheckTwoPair(checkCol) == 1)
           {
               return 2;
           }

            // ワンペアがあるかを調べる
           if (CheckOnePair(checkCol) == 1)
           {
               return 1;
           }  
 
           // 役がそろってないならば
           return 0;
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) return 1;
    }
    return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    int count[13] = {0}, pair = 0;
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 2) pair++;
    }
    return (pair == 2);
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 3) return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int count[13] = {0};
    for (int i = 0; i < 5; i++) count[checkCol[i] - 1]++;
    
    for (int i = 0; i < 13; i++) {
        if (count[i] == 4) return 1;
    }
    return 0;
}



// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    for (int i = 0; i < 5; i++) {
        if (checkRow[i] != checkRow[0]) return 0;
    }
    return 1;
}


// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.17: ウサギとカメのかけ比べをシミュレーションするプログラム
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define MASU_SIZE 71

void printPosition(int rabbit, int turtle);
int checkWinner(int rabbit, int turtle);
void moveTurtle(int *turtle);
void moveRabbit(int *rabbit);
void printWinner(int w);

int main()
{
    int rabbitPosition = 1;
    int turtlePosition = 1;
    int winner = 0;

    srand((unsigned)time(NULL));

    printf("スタート!!\n");

    while (winner == 0)
    {
        Sleep(300);

        moveTurtle(&turtlePosition);
        moveRabbit(&rabbitPosition);

        winner = checkWinner(rabbitPosition, turtlePosition);

        printPosition(rabbitPosition, turtlePosition);
    }

    printWinner(winner);

    getchar();
    return 0;
}

void printPosition(int rabbit, int turtle)
{
    int i;

    printf("\n");

    for (i = 1; i <= MASU_SIZE; i++)
    {
        if (i == rabbit && i == turtle)
        {
            printf("痛い!!!");
        }
        else if (i == rabbit)
        {
            printf("R");
        }
        else if (i == turtle)
        {
            printf("T");
        }
        else
        {
            printf("-");
        }
    }

    printf("\n");
}

int checkWinner(int rabbit, int turtle)
{
    if (rabbit >= MASU_SIZE && turtle >= MASU_SIZE)
        return 3;
    else if (turtle >= MASU_SIZE)
        return 2;
    else if (rabbit >= MASU_SIZE)
        return 1;

    return 0;
}

void moveTurtle(int *turtle)
{
    int r = rand() % 10 + 1;

    if (r <= 5)
        *turtle += 3;   // 早歩き
    else if (r <= 8)
        *turtle += 1;   // ゆっくり
    else
        *turtle -= 6;   // すべり

    if (*turtle < 1) *turtle = 1;
}

void moveRabbit(int *rabbit)
{
    int r = rand() % 10 + 1;

    if (r <= 2)
        *rabbit += 0;   // 休み
    else if (r <= 4)
        *rabbit += 9;   // 大ジャンプ
    else if (r <= 6)
        *rabbit += 1;   // 小ジャンプ
    else if (r <= 8)
        *rabbit -= 2;   // すべり
    else
        *rabbit -= 12;  // 大転落

    if (*rabbit < 1) *rabbit = 1;
}

void printWinner(int w)
{
    printf("\n");

    if (w == 1)
        printf("🐇 ウサギの勝ち!\n");
    else if (w == 2)
        printf("🐢 カメの勝ち!\n");
    else
        printf("引き分け!\n");
}
7.18: 機械語プログラミング
  • a: 番兵制御ループを使って10個の正の値を読み込み、それらの和を計算してプリントする
source
00 1010 変数Bに数値を読み込む(0を読み込ませる 総和用)
01 1009 変数Aに数値を読み込む(正の値を読み込ませる)
02 2009 変数Aの値をアキュムレーターにロード
03 4107 アキュムレーターの値が負のとき(番兵値の時)実行終了
04 3010 変数Bの値とアキュムレーターの値を足す
05 2110 アキュムレーターの値を変数Bにストア
06 4001 01にジャンプ
07 1110 総和を出力
08 4300 実行終了
09 変数A
10 変数B
  • b: カウンタ制御ループを使って7個の数値(正の値と負の値を混ぜて)読み込み、それらの平均を計算してプリントする
source
00 1019 変数A0を読み込む
01 1020 変数B7を読み込む
02 1021 変数C1を読み込む
03 1023 変数Eに値0を読み込む(総和用)
04 2019 変数Aをアキュムレーターにロード
05 3021 変数Cの値をアキュムレーターに加える
06 3120 アキュムレーターから変数Bの値を引く
07 4214 アキュムレーターの値が0,すなわち7個値が入力されたならば
08 2119 アキュムレーターの値を変数Aにストア
09 1022 変数Dに値を読み込む
10 2022 変数Dの値をアキュムレータにロード
11 3023 変数Eの値をアキュムレータに加える
12 2123 アキュムレーターの値を変数Eにストア
13 4004 04にジャンプ
14 2023 変数Eの値をアキュムレーターにロード
15 3220 アキュムレータの値を変数Bの値で割る
16 2120 アキュムレータから変数Bに値をストア
17 1120 変数Bの値を端末に書き込む
18 4300 実行終了

19 0000 変数A
20 0000 変数B
21 0000 変数C
22 0000 変数D
23 0000 変数E
  • c: 一連の数値を読み込み、それらのうちの最大値を求めてプリントする(最初に読み込んだ数値が処理すべき数値の個数を表す)
source
00 1017 変数Aに数値(入力個数を読み込む)
01 1018 変数Bに数値0を読み込む(カウンタ制御)
02 1019 変数Cに数値1を読み込む(カウンタ制御)
03 1020 変数Dに数値0を読み込む(max)
03 2018 変数Bをアキュムレータにロードする
04 3019 変数Cの値をアキュムレーターに加える
05 3117 アキュムレーターから変数Aの値を引く
06 4212 アキュムレーターの値が0,すなわち入力個数分データを読み込んだなら
08 2118 アキュムレータの値を変数Bにストア
07 1021 変数Eに数値を読み込む(データ)
08 2020 変数Dをアキュムレーターに読み込む
09 3121 アキュムレーターから変数Eの値を引く
10 4112 アキュムレーターが負の時,すなわち,今までより大きいデータであったとき
11 4003 03にジャンプ
12 2021 変数Eをアキュムレータに読み込む
13 2120 アキュムレータの値を変数Dにストア
14 4003 03にジャンプ
15 1120 変数Dの値を端末に書き込む
16 4300 実行終了

17 0000 変数A
18 0000 変数B
19 0000 変数C
20 0000 変数D
21 0000 変数E
7.19: コンピュータシミュレータ
source
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

#define DEBUG(name) { printf("\nDEBUG (" #name ") %d\n\n", name); }

// 入出力命令
#define READ  10 // 端末からメモリ内の指定した番地に1ワード書き込む
#define WRITE 11 // メモリ内の指定した番地から端末に1ワード書き込む

// ロード/ストア命令
#define LOAD  20 // メモリ内の指定した番地からアキュムレータに1ワードロードする
#define STORE 21 // アキュムレータからメモリ内の指定した番地に1ワードストアする

// 算術演算命令
#define ADD         30 // アキュムレータにメモリ内の指定した番地にある1ワードを足す(結果はアキュムレータ内に残る)
#define SUBTRACT    31 // アキュムレータにメモリ内の指定した番地にある1ワードを引く(結果はアキュムレータ内に残る)
#define DIVIDE      32 // アキュムレータにメモリ内の指定した番地にある1ワードで割る(結果はアキュムレータ内に残る)
#define MULTIPLY    33 // アキュムレータにメモリ内の指定した番地にある1ワードを掛ける(結果はアキュムレータ内に残る)

// 分岐命令
#define BRANCH     40 // メモリ内の指定した番地に無条件分岐する
#define BRANCHENG  41 // アキュムレータが負のとき、メモリ内の指定した番地に分岐する
#define BRANCHZERO 42 // アキュムレータが0のとき、メモリ内の指定した番地に分岐する
#define HALT       43 // 停止する つまりプログラムが実行を終了する
 
#define MEMORY_SIZE 100 // メモリの大きさ

// レジスタの内容とメモリの内容をダンプする関数
void printDamp(int, int, int, int, int, int []);

int main()
{ 
    static int memory[MEMORY_SIZE];                  // メモリモデル
    int accumulator = 0;                             // レジスタ
    int instructionCounter = 0;                      // 次に実行する命令が格納されたメモリ番地を格納
    int instructionRegister;                         // 次に実行する命令
    int operationCode;                               // 現在実行中の命令コードを格納
    int operand = 0;                                 // 現在の命令が作用するメモリ番地
    int endFlag = 0;          
   

    // 起動メッセージを表示
    printf("*** Simpletronへようこそ! *** \n");
    printf("*** プログラムは1命令(または1データ)ずつ入力してください。         ***\n");
    printf("*** メモリ番地と?マークを表示しますから、その番地に入れるワードを   ***\n");
    printf("*** タイプしてください                                             ***\n");
    printf("*** プログラムを入力し終わったら、最後に-99999をタイプしてください。***\n");


    // プログラムがロードされる間
    while (0 == endFlag)
    {
        // 命令を入力
        printf("%+03d ? ", operand);
        scanf("%d", &memory[operand]);

        if (memory[operand] == -99999)
        {
            endFlag = 1;
            memory[operand] = 0;
        }
        else if (-9999 <= memory[operand] && memory[operand] <= 9999)
        {
            operand++;
            fflush(stdin);
        }
        else
        {
            printf("\n不正な値です -9999 - 9999 までの値を入力してください(ただし、-99999は終了フラグを立てるため許されます)\n\n");
        }
    }
   
    if (operand <= 0)
    {
        printf("命令はロードされていません\n");
        endFlag = 1;
    }
    else
    {
        printf("*** プログラムのロードが完了しました ***\n");
        printf("*** プログラムの実行を開始します     ***\n");
        endFlag = 0;
    }

    while (endFlag == 0)
    {
        // 命令を取り出す
        instructionRegister = memory[instructionCounter];
        DEBUG(instructionRegister)

        // 次の命令にカウンタを更新
        instructionCounter++;

        // 命令レジスタから命令コードを取り出す
        operationCode = instructionRegister / 100;

        // 命令レジスタからオペランドを取り出す
        operand = instructionRegister % 100;

       // 命令判別
       switch (operationCode)
       {
          // 入力命令
          case READ:
            printf("データを入力してください\n");
            scanf("%d", &memory[operand]);
            break;

          // 出力命令
          case WRITE:
            printf("%+5d\n", memory[operand]); 
            break;

          // ロード命令
          case LOAD:
             accumulator = memory[operand];
             break;

          // ストア命令
          case STORE:
             memory[operand] = accumulator;
             break;

          // 加算命令
          case ADD:
             accumulator += memory[operand];

             if (accumulator < -9999)
             {
                 fprintf(stderr, "*** 演算結果のオーバーフロー ***\n"
                               "*** Simpletronは以上終了しました ***\n\n");
                 printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
                 return -1;
             }
             else if (accumulator > 9999)
             {
                 fprintf(stderr, "*** 演算結果のオーバーフロー ***\n"
                               "*** Simpletronは以上終了しました ***\n\n");
                 printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
                 return -1;
             }
             break;

          // 引き算命令
          case SUBTRACT:
             accumulator -= memory[operand];

             if (accumulator < -9999)
             {
                 fprintf(stderr, "*** 演算結果のオーバーフロー ***\n"
                               "*** Simpletronは以上終了しました ***\n\n");
                 printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
                 return -1;
             }
             else if (accumulator > 9999)
             {
                 fprintf(stderr, "*** 演算結果のオーバーフロー ***\n"
                               "*** Simpletronは以上終了しました ***\n\n");
                 printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
                 return -1;
             }
             break;

          // 割り算命令
          case DIVIDE:

             // 0による除算ならば
             if (memory[operand] == 0)
             {
                 fprintf(stderr, "*** ゼロで割ろうとした ***\n"
                                 "*** Simpletronは以上終了しました ***\n\n");
                 printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
                 return -1;
             }
             accumulator /= memory[operand];
             break;

          // 掛け算命令
          case MULTIPLY:
             accumulator *= memory[operand];
             break;

          // 無条件分岐命令
          case BRANCH:

             // 無条件にジャンプ
             instructionCounter = operand;
             break;

          // アキュムレータが負のとき分岐する命令
          case BRANCHENG:
          
             // アキュムレータが負なら
             if (accumulator < 0)
             {
                 // ジャンプ先を格納
                 instructionCounter = operand;
             }
             break;

          // アキュムレータが0のとき分岐する命令
          case BRANCHZERO:
             if (accumulator == 0)
             {
                 instructionCounter = operand;
             }
             break;

          // 停止命令
          case HALT:
             endFlag = 1;
             printf("*** Simpletronは終了しました ***\n\n"); 
             printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);           
             break;
 
          // 不正な命令
          default:
             fprintf(stderr, "*** 不正な命令コード ***\n"
                     "*** Simpletronは以上終了しました ***\n\n");
             printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);                
             return -1;         
        }
    }
    getch();

    return 0;
}

// レジスタの内容とメモリの内容をダンプする関数
void printDamp(int accu, int instructionC, int instructionR, int operation, int operand, int m[])
{
     int i, j;


     printf("レジスタ:                  \n");
     printf("アキュムレータ %+05d          \n", accu);
     printf("命令カウンタ      %02d          \n", instructionC);
     printf("命令レジスタ   %+5d          \n", instructionR);
     printf("命令コード        %02d          \n", operation);
     printf("オペランド        %02d          \n\n\n", operand);
     printf("メモリ:                      \n");
     printf("   ");
  
     for (i = 0; i < 10; i++)
     {
         printf("%5d ", i);  
     }
     printf("\n");

     for (i = 0; i < 100; i += 10)
     {
         printf("%2d ", i);
   
         for (j = i; j < i + 10; j++)
         {
             printf("%+05d ", m[j]);
         }
         printf("\n");
     }
}
7.20: リスト7.14(P.269)のカード混合・分配プログラムをカードを混ぜる操作と配る操作を同じ関数で行うように変更したプログラム(この関数ではリスト7.14の関数Shuffleと同じような1個のネストした反復構造を使う)
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void ShuffleAndDeal(int [][13], const char *[], const char *[]);

int CheckOnePair(int []);
int CheckTwoPair(int []);
int CheckThreeCard(int []);
int CheckFourCard(int []);
int CheckFlush(int []);
int CheckStraight(int []);

int main()
{
   const char *suit[4] = {"ハート", "ダイア", "クラブ", "スペード"};
   const char *face[13] = {"エース", "2", "3", "4", "5", "6", "7", "8",
                           "9", "10", "ジャック", "クイーン", "キング"};
   int deck[4][13] = {0};

   srand(time(NULL));
   
   ShuffleAndDeal(deck, suit, face);

   return 0;
}

void ShuffleAndDeal(int wDeck[][13], const char *wSuit[], const char *wFace[])
{
   int card, row, column;

   for (card = 1; card <= 52; card++)
   {
       row = rand() % 4;
       column = rand() % 13;

       while (wDeck[row][column] != 0)
       {
           row = rand() % 4;
           column = rand() % 13;
       }
 
       wDeck[row][column] = card;
       printf("%8s の %-8s%c", wSuit[row], wFace[column],
                        card % 2 == 0 ? '\n' : '\t');
   }
}

// ワンペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckOnePair(int checkCol[])
{
   int i, j;

   for (i = 0; i < 4; i++)
   {
      for (j = i + 1; j < 5; j++)
      {
          // 同じ数字のカードが2枚含まれているならば
          if (checkCol[i] == checkCol[j])
          {
              return 1;
          }
      }
   }
   // 同じ数字のカードが2枚含まれていないので
   return 0;
}

// ツーペアを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckTwoPair(int checkCol[])
{
    if ((checkCol[0] == checkCol[1]) && (checkCol[2] == checkCol[3]))
    {
        return 1;
    }
    else if ((checkCol[0] == checkCol[1]) && (checkCol[3] == checkCol[4])) 
    {
        return 1;
    }
    else if ((checkCol[1] == checkCol[2]) && (checkCol[3] == checkCol[4]))
    {
        return 1;
    }
  
    // ツーペアではない
    return 0;
}

// スリーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckThreeCard(int checkCol[])
{
    int i, j;
    int n;

    n = 0;

    for (i = 0; i < 4; i++)
    {
        for (j = i + 1; j < 5; j++)
        {
            if (checkCol[i] == checkCol[j])
            {
                n++;
            }
        }
    }

    if (n == 3)
    {
        return 1;
    }
    return 0;
}

// フォーカードを含んでいるかを判定する関数
// 1:含んでいる 0:含んでいない
int CheckFourCard(int checkCol[])
{
    int i, j;
    int n;

    n = 0;

    for (i = 0; i < 4; i++)
    {
        for (j = i + 1; j < 5; j++)
        {
            if (checkCol[i] == checkCol[j])
            {
                n++;
            }
        }
    }

    if (n == 4)
    {
        return 1;
    }
    return 0;
}

// フラッシュかを判定する関数
// 1:フラッシュである 0:フラッシュでない
int CheckFlush(int checkRow[])
{
    int i;
    int type;

    // 最初のカードの柄を記録
    type = checkRow[0];

    for (i = 1; i < 5; i++)
    {
        // 異なるカードの柄が見つかったならば
        if (checkRow[i] != type)
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードの柄が同じ場合である
    return 1;
}

// ストレートかを判定する関数
// 1:ストレートである 0:ストレートでない
int CheckStraight(int checkCol[])
{
    int i;
    int count;
    int tmp;

    // 昇順にソート
    for (count = 1; count <= 4; count++)
    {
        for (i = 0; i < 4; i++)
        {
            if (checkCol[i] > checkCol[i + 1])
            {
               tmp = checkCol[i];
               checkCol[i] = checkCol[i + 1];
               checkCol[i + 1] = tmp;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (checkCol[i] + 1 != checkCol[i + 1])
        {
            return 0;
        }
    }

    // ここまでくるのは全てのカードが連続な場合である
    return 1;
}
7.24: クイックソート
source
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void print(int [], int);

void quickSort(int [], int, int);

int main()
{
    int data[] = {37, 2, 6, 4, 89, 8, 10, 12, 68, 45};
    int i;
    

    quickSort(data, 0, sizeof(data) / sizeof(data[0]) - 1);

    getch();
    return 0;
}

void quickSort(int d[], int left, int right)
{
    int tmp;
    int i, j;
   
    if (left >= right)
    {
        return;  
    }
    i = left;
    j = right;

    while (left < right)
    {
        for (; right > left; right--)
        {
           if (d[left] > d[right])
           {
               tmp = d[left];
               d[left] = d[right];
               d[right] = tmp;
               left++;
               print(d, 10);
               break;
           }
        }

        for (; left < right; left++)
        {
           if (d[left] > d[right])
           {
               tmp = d[left];
               d[left] = d[right];
               d[right] = tmp;
               print(d, 10);
               right--;
               break;
           }
        }
    }
     printf("left %d right %d\n", left, right);
    getch();
    quickSort(d, i, left - 1);
    quickSort(d, right + 1, j);
}

void print(int d[], int size)
{
    int i;
    for (i = 0; i < size; i++)
    {
        printf("%d\n", d[i]);
    }
    printf("\n\n");
}
7.25: 迷路からの脱出
  • 脱出アルゴリズム: 右手で右側にある壁を触りながら前方に歩き出す。決して壁から手を離してはいけない。迷路が右に折れていたら壁に沿って右に曲がる。このように進んでいけば、壁から手を離さないかぎり必ず迷路の出口に着く(出口がないと入り口に戻ってくる)
source
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <windows.h>

#define ROW 12
#define COL 12

#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

void printMaze(char [][COL], int, int);

void mazeTraverse(char [][COL], int, int);

int main()
{
    char maze[ROW][COL] = {{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
                           {'#', '.', '.', '.', '#', '.', '.', '.', '.', '.', '.', '#'},
                           {'.', '.', '#', '.', '#', '.', '#', '#', '#', '#', '.', '#'},
                           {'#', '#', '#', '.', '#', '.', '.', '.', '.', '#', '.', '#'},
                           {'#', '.', '.', '.', '.', '#', '#', '#', '.', '#', '.', '#'},
                           {'#', '#', '#', '#', '.', '#', '.', '#', '.', '#', '.', '.'},
                           {'#', '.', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
                           {'#', '#', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
                           {'#', '.', '.', '.', '.', '.', '.', '.', '.', '#', '.', '#'},
                           {'#', '#', '#', '#', '#', '#', '.', '#', '#', '#', '.', '#'},
                           {'#', '.', '.', '.', '.', '.', '.', '.', '#', '.', '.', '#'},
                           {'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};
    mazeTraverse(maze, 2, 0);
    getch();
    return 0;
}

void printMaze(char m[][COL], int row, int col)
{
    int i, j;


    for (i = 0; i < row; i++)
    {
       for (j = 0; j < col; j++)
       {
           putchar(m[i][j]);
       }
       putchar('\n');
    }
}

// 右手の法則を使って迷路を探索する関数
void mazeTraverse(char m[][COL], int rowS, int colS)
{
    static int direction = RIGHT;
    
    printf("row %d col %d\n", rowS, colS);
    printMaze(m, ROW, COL);
    Sleep(500);
    printf("\n");

    // 進行方向が右
    if (direction == RIGHT)
    {
        // 右側に壁がないならば
        if (m[rowS + 1][colS] == '.' || m[rowS + 1][colS] == 'X')
        {
            direction = DOWN;
            printf("下に方向転換しました\n");

            // ゴールならば
            if (rowS + 1 == 5 && colS == 11)
            {
                m[rowS + 1][colS] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS + 1][colS] = 'X';
                mazeTraverse(m, rowS + 1, colS);
            }
        }
        // 前方に進めるならば
        else if (m[rowS][colS + 1] == '.' || m[rowS][colS + 1] == 'X')
        {
            // ゴールならば
            if (rowS == 5 && colS + 1 == 11)
            {
                m[rowS][colS + 1] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS][colS + 1] = 'X';
                mazeTraverse(m, rowS, colS + 1);
            }
        }
        // 左側に方向転換
        else
        {
           direction = UP;
           printf("上に方向転換しました\n");
           mazeTraverse(m, rowS, colS);
        }
    }
    // 進行方向が下
    else if(direction == DOWN)
    {
        // 右側に壁がないならば
        if (m[rowS][colS - 1] == '.' || m[rowS][colS - 1] == 'X')
        {
            direction = LEFT;
            printf("左に方向転換しました\n");

            // ゴールならば
            if (rowS == 5 && colS - 1 == 11)
            {
                m[rowS][colS - 1] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS][colS - 1] = 'X';
                mazeTraverse(m, rowS, colS - 1);
            }
        }
        // 前方に進めるならば
        else if (m[rowS + 1][colS] == '.' || m[rowS + 1][colS] == 'X')
        {
            // ゴールならば
            if (rowS + 1 == 5 && colS == 11)
            {
                m[rowS + 1][colS] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS + 1][colS] = 'X';
                mazeTraverse(m, rowS + 1, colS);
            }
        }
        // 左に方向転換
        else
        {
           direction = RIGHT;
           printf("右に方向転換しました\n");
           mazeTraverse(m, rowS, colS);
        }
    }
    // 進行方向が左
    else if(direction == LEFT)
    {
        // 右側に壁がないならば
        if (m[rowS - 1][colS] == '.' || m[rowS - 1][colS] == 'X')
        {
            direction = UP;
            printf("上に方向転換しました\n");

            // ゴールならば
            if (rowS - 1 == 5 && colS == 11)
            {
                m[rowS - 1][colS] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS - 1][colS] = 'X';
                mazeTraverse(m, rowS - 1, colS);
            }
        }
        // 前方に進めるならば
        else if (m[rowS][colS - 1] == '.' || m[rowS][colS - 1] == 'X')
        {
            // ゴールならば
            if (rowS == 5 && colS - 1 == 11)
            {
                m[rowS][colS - 1] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
               m[rowS][colS - 1] = 'X';
               mazeTraverse(m, rowS, colS - 1);
            }
        }
        // 左に方向転換
        else
        {
           direction = DOWN;
           printf("下に方向転換しました\n");
           mazeTraverse(m, rowS, colS);
        }
    }
     // 進行方向が上
    else if(direction == UP)
    {
        // 右側に壁がないならば
        if (m[rowS][colS + 1] == '.' || m[rowS][colS + 1] == 'X')
        {
            direction = RIGHT;
            printf("右に方向転換しました\n");

            // ゴールならば
            if (rowS == 5 && colS + 1 == 11)
            {
                m[rowS][colS + 1] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS][colS + 1] = 'X';
                mazeTraverse(m, rowS, colS + 1);
            }
        }
        // 前方に進めるならば
        else if (m[rowS - 1][colS] == '.' || m[rowS - 1][colS] == 'X')
        {
             // ゴールならば
            if (rowS - 1 == 5 && colS == 11)
            {
                m[rowS - 1][colS] = 'X';
                printf("ゴール\n");
                // 迷路を表示
                printMaze(m, ROW, COL);
            }
            else
            {
                m[rowS - 1][colS] = 'X';
                mazeTraverse(m, rowS - 1, colS);
            }
        }
        // 左に方向転換
        else
        {
           direction = LEFT;
           printf("左に方向転換しました\n");
           mazeTraverse(m, rowS, colS);
        }
    }
}
7.26: ランダムに迷路を作成する
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define ROW 12
#define COL 12

#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

char maze[ROW][COL];
int visited[ROW][COL];
int dirRow[4] = {-1, 0, 1, 0}; // UP, RIGHT, DOWN, LEFT
int dirCol[4] = {0, 1, 0, -1};

void printMaze() {
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++)
            putchar(maze[i][j]);
        putchar('\n');
    }
    putchar('\n');
}

int isValid(int r, int c) {
    return r > 0 && r < ROW - 1 && c > 0 && c < COL - 1;
}

void shuffleDirections(int d[4][2]) {
    for (int i = 0; i < 4; i++) {
        int j = rand() % 4;
        int tmp0 = d[i][0], tmp1 = d[i][1];
        d[i][0] = d[j][0]; d[i][1] = d[j][1];
        d[j][0] = tmp0;    d[j][1] = tmp1;
    }
}

void dfs(int r, int c) {
    visited[r][c] = 1;
    maze[r][c] = '.';

    int d[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
    shuffleDirections(d);

    for (int i = 0; i < 4; i++) {
        int nr = r + d[i][0];
        int nc = c + d[i][1];
        if (isValid(nr, nc) && !visited[nr][nc]) {
            maze[r + d[i][0] / 2][c + d[i][1] / 2] = '.';
            dfs(nr, nc);
        }
    }
}

void mazeGenerator(int *startRow, int *startCol, int *goalRow, int *goalCol) {
    srand((unsigned int)time(NULL));

    for (int i = 0; i < ROW; i++)
        for (int j = 0; j < COL; j++) {
            maze[i][j] = '#';
            visited[i][j] = 0;
        }

    *startRow = (rand() % ((ROW - 2) / 2)) * 2 + 1;
    *startCol = 0;
    maze[*startRow][*startCol] = '.';

    dfs(*startRow, 1); // 掘り始めはスタートの隣

    *goalRow = (rand() % ((ROW - 2) / 2)) * 2 + 1;
    *goalCol = COL - 1;
    maze[*goalRow][*goalCol] = 'G'; // ゴールは右端
    maze[*goalRow][COL - 2] = '.';  // ゴールの左隣も通路に
}

int isGoal(int r, int c) {
    return maze[r][c] == 'G';
}

int isPassable(int r, int c) {
    return r >= 0 && r < ROW && c >= 0 && c < COL && (maze[r][c] == '.' || maze[r][c] == 'G');
}

void mazeTraverse(int row, int col, int direction) {
    if (isGoal(row, col)) {
        maze[row][col] = 'X';
        printMaze();
        printf("ゴールに到達しました!\n");
        return;
    }

    maze[row][col] = 'X';
    printMaze();
    Sleep(100);

    for (int i = 0; i < 4; i++) {
        int tryDir = (direction + 1 + i) % 4; // 右→前→左→後ろの順
        int nextRow = row + dirRow[tryDir];
        int nextCol = col + dirCol[tryDir];

        if (isPassable(nextRow, nextCol)) {
            mazeTraverse(nextRow, nextCol, tryDir);
            return;
        }
    }
}

int main() {
    int startRow, startCol, goalRow, goalCol;
    mazeGenerator(&startRow, &startCol, &goalRow, &goalCol);

    printf("スタート: (%d, %d)\n", startRow, startCol);
    printf("ゴール  : (%d, %d)\n", goalRow, goalCol);
    printMaze();

    mazeTraverse(startRow, startCol, RIGHT);
    return 0;
}
7.27: 任意なサイズの迷路
source
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

int dirRow[4] = {-1, 0, 1, 0}; // UP, RIGHT, DOWN, LEFT
int dirCol[4] = {0, 1, 0, -1};

void printMaze(char **maze, int rowSize, int colSize) {
    for (int i = 0; i < rowSize; i++) {
        for (int j = 0; j < colSize; j++)
            putchar(maze[i][j]);
        putchar('\n');
    }
    putchar('\n');
}

void shuffleDirections(int d[4][2]) {
    for (int i = 0; i < 4; i++) {
        int j = rand() % 4;
        int tmp0 = d[i][0], tmp1 = d[i][1];
        d[i][0] = d[j][0]; d[i][1] = d[j][1];
        d[j][0] = tmp0;    d[j][1] = tmp1;
    }
}

void dfs(char **maze, int **visited, int rowSize, int colSize, int r, int c, int *lastRow) {
    visited[r][c] = 1;
    maze[r][c] = '.';
    *lastRow = r;

    int d[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
    shuffleDirections(d);

    for (int i = 0; i < 4; i++) {
        int nr = r + d[i][0], nc = c + d[i][1];
        if (nr > 0 && nr < rowSize - 1 && nc > 0 && nc < colSize - 1 && !visited[nr][nc]) {
            maze[r + d[i][0] / 2][c + d[i][1] / 2] = '.';
            dfs(maze, visited, rowSize, colSize, nr, nc, lastRow);
        }
    }
}

void mazeGenerator(char **maze, int **visited, int rowSize, int colSize,
                   int *startRow, int *startCol, int *goalRow, int *goalCol) {
    srand((unsigned int)time(NULL));

    for (int i = 0; i < rowSize; i++)
        for (int j = 0; j < colSize; j++) {
            maze[i][j] = '#';
            visited[i][j] = 0;
        }

    *startRow = (rand() % ((rowSize - 2) / 2)) * 2 + 1;
    *startCol = 0;
    maze[*startRow][*startCol] = '.';

    int lastRow = *startRow;
    dfs(maze, visited, rowSize, colSize, *startRow, 1, &lastRow);

    *goalRow = lastRow;
    *goalCol = colSize - 1;
    maze[*goalRow][*goalCol] = 'G';
    maze[*goalRow][colSize - 2] = '.'; // ゴールの左隣を通路に
}

int isGoal(char **maze, int r, int c) {
    return maze[r][c] == 'G';
}

int isPassable(char **maze, int rowSize, int colSize, int r, int c) {
    return r >= 0 && r < rowSize && c >= 0 && c < colSize &&
           (maze[r][c] == '.' || maze[r][c] == 'G' || maze[r][c] == 'X');
}

void mazeTraverse(char **maze, int rowSize, int colSize, int row, int col, int direction) {
    if (isGoal(maze, row, col)) {
        maze[row][col] = 'X';
        printMaze(maze, rowSize, colSize);
        printf("ゴールに到達しました!\n");
        return;
    }

    maze[row][col] = 'X';
    printMaze(maze, rowSize, colSize);
    Sleep(50);

    // 右→前→左→後退の順に試す
    int dirs[4] = {
        (direction + 1) % 4, // 右
        direction,           // 前
        (direction + 3) % 4, // 左
        (direction + 2) % 4  // 後退
    };

    for (int i = 0; i < 4; i++) {
        int tryDir = dirs[i];
        int nextRow = row + dirRow[tryDir];
        int nextCol = col + dirCol[tryDir];
        if (isPassable(maze, rowSize, colSize, nextRow, nextCol)) {
            mazeTraverse(maze, rowSize, colSize, nextRow, nextCol, tryDir);
            return;
        }
    }
}

int main() {
    int rowSize = 21, colSize = 31; // 任意サイズ(奇数推奨)
    int startRow, startCol, goalRow, goalCol;

    char **maze = malloc(rowSize * sizeof(char *));
    int **visited = malloc(rowSize * sizeof(int *));
    for (int i = 0; i < rowSize; i++) {
        maze[i] = malloc(colSize * sizeof(char));
        visited[i] = malloc(colSize * sizeof(int));
    }

    mazeGenerator(maze, visited, rowSize, colSize, &startRow, &startCol, &goalRow, &goalCol);
    printf("スタート: (%d, %d)\n", startRow, startCol);
    printf("ゴール  : (%d, %d)\n", goalRow, goalCol);
    printMaze(maze, rowSize, colSize);
    mazeTraverse(maze, rowSize, colSize, startRow, startCol, RIGHT);

    for (int i = 0; i < rowSize; i++) {
        free(maze[i]);
        free(visited[i]);
    }
    free(maze);
    free(visited);
    return 0;
}
7.28: 関数へのポインタの配列
source
#include <stdio.h>
#include <conio.h>

#define STUDENTS 3
#define EXAMS 4

void minimum(int [][EXAMS], int, int);
void maximum(int [][EXAMS], int, int);
void average(int [][EXAMS], int, int);
void printArray(int [][EXAMS], int, int);

int main()
{
    int select;
    int endFlag = 0;
    int studentGrades[STUDENTS][EXAMS] = {{66, 50, 50, 60}, 
                                          {50, 40, 50, 50},
                                          {95, 56, 60, 60}};
    void (*processGrades[4])(int [][EXAMS], int, int);

    processGrades[0] = printArray;
    processGrades[1] = minimum;
    processGrades[2] = maximum;
    processGrades[3] = average;

     
    while (endFlag == 0)
    {
       printf("選択した番号を入力してください:\n");
       printf("     0 成績の配列をプリントする\n");
       printf("     1 最低点を見つける\n");
       printf("     2 最高点を見つける\n");
       printf("     3 各学生の全科目の平均点をプリントする\n");
       printf("     4 プログラムを終了する\n");

       scanf("%d", &select);

       if (select == 4)
       {
           endFlag = 1;
       }
       else
       {
           (*processGrades[select])(studentGrades, STUDENTS, EXAMS);
       }
    }

    
    
    getch();
    return 0;
}

void minimum(int grades[][EXAMS], int pupils, int tests)
{
    int i, j, lowGrade = 100;
    
    for (i = 0; i <= pupils - 1; i++)
    {
       for (j = 0; j <= tests - 1; j++)
       {
           if (grades[i][j] < lowGrade)
           {
               lowGrade = grades[i][j];
           }
       }
    }

    printf("\n\n最低点: %d\n", lowGrade);
}

void maximum(int grades[][EXAMS], int pupils, int tests)
{
    int i, j, highGrade = 0;

    for (i = 0; i <= pupils - 1; i++)
    {
       for (j = 0; j <= tests - 1; j++)
       {
           if (grades[i][j] > highGrade)
           {
               highGrade = grades[i][j];
           }
       }
    }
    printf("\n\n最高点: %d\n", highGrade);
}

void printArray(int grades[][EXAMS], int pupils, int tests)
{
    int i, j;

    printf("                 [0]  [1]  [2]  [3]");     
    for (i = 0; i <= pupils - 1; i++)
    {
        printf("\nstudentsGrades[%d] ", i);
        for (j = 0; j <= tests - 1; j++)
        {
            printf("%-5d", grades[i][j]);
        }
    }
    printf("\n\n");
}

void average(int grades[][EXAMS], int pupils, int tests)
{
    int i, j;
    int total;

    for (i = 0; i <= pupils - 1; i++)
    {
        total = 0;

        for (j = 0; j <= tests - 1; j++)
        {
           total += grades[i][j];
        }

        printf("学生 %d の平均点は %.2f\n", 
                   i, (double)total / tests);
    }
    printf("\n");
}
7.29: Simpletronシミュレータの改造
  • a: 大きなプログラムを処理できるようにメモリを1000番地まで拡大
  • b: 剰余計算の追加
  • c: 指数計算の追加
  • d: SML命令を10進数でなく16進数で表せるように改造
  • e: ニューライン文字を出力できるように改造
  • f: 浮動小数点も扱えるように改造
  • g: 文字列も入力できるように改造
  • h: gの形式で格納されている文字列を出力できるように改造
source
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

#define DEBUG(name) { printf("\nDEBUG (" #name ") 0x%04X\n\n", name); }

// 命令コード定義(上位8ビット)
#define READ        0x0A
#define WRITE       0x0B
#define PRINTLN     0x0C
#define READSTR     0x0D
#define WRITESTR    0x0E
#define LOAD        0x14
#define STORE       0x15
#define ADD         0x1E
#define SUBTRACT    0x1F
#define DIVIDE      0x20
#define MULTIPLY    0x21
#define MOD         0x22
#define POWER       0x23
#define BRANCH      0x28
#define BRANCHENG   0x29
#define BRANCHZERO  0x2A
#define HALT        0x2B

#define MEMORY_SIZE 1000

void printDamp(double, int, int, int, int, double[]);

int main()
{
    static double memory[MEMORY_SIZE];
    double accumulator = 0.0;
    int instructionCounter = 0;
    int instructionRegister;
    int operationCode;
    int operand = 0;
    int endFlag = 0;

    printf("*** Simpletronへようこそ! ***\n");
    printf("*** 命令は16進数で入力してください(例: 0x0A14)***\n");
    printf("*** プログラムを入力し終わったら、最後に -0x1869F を入力してください(-99999)***\n");

    while (0 == endFlag)
    {
        printf("%03X ? ", operand);
        scanf("%x", (int*)&memory[operand]); // 整数として読み込む

        if ((int)memory[operand] == -0x1869F) // -99999
        {
            endFlag = 1;
            memory[operand] = 0.0;
        }
        else if ((int)memory[operand] >= -0x270F && (int)memory[operand] <= 0x270F) // -9999〜9999
        {
            operand++;
        }
        else
        {
            printf("\n不正な値です。-9999〜9999の範囲で入力してください(-99999は終了)\n\n");
        }
    }

    if (operand <= 0)
    {
        printf("命令はロードされていません\n");
        endFlag = 1;
    }
    else
    {
        printf("*** プログラムのロードが完了しました ***\n");
        printf("*** プログラムの実行を開始します     ***\n");
        endFlag = 0;
    }

    while (endFlag == 0)
    {
        instructionRegister = (int)memory[instructionCounter];
        DEBUG(instructionRegister)

        instructionCounter++;

        operationCode = instructionRegister >> 8;
        operand       = instructionRegister & 0xFF;

        switch (operationCode)
        {
            case READ:
                printf("データを入力してください(実数): ");
                scanf("%lf", &memory[operand]);
                break;

            case WRITE:
                printf("出力: %+f\n", memory[operand]);
                break;

            case PRINTLN:
                printf("\n");
                break;

            case READSTR:
            {
                char input[256];
                printf("文字列を入力してください(最大255文字): ");
                scanf("%255s", input);

                int len = strlen(input);
                memory[operand] = (double)len;

                for (int i = 0; i < len && (operand + 1 + i) < MEMORY_SIZE; i++)
                {
                    memory[operand + 1 + i] = (double)(unsigned char)input[i];
                }
                break;
            }

            case WRITESTR:
            {
                int len = (int)memory[operand];
                printf("文字列出力: ");
                for (int i = 0; i < len && (operand + 1 + i) < MEMORY_SIZE; i++)
                {
                    char c = (char)((int)memory[operand + 1 + i]);
                    if (isprint(c))
                        putchar(c);
                    else
                        putchar('?');
                }
                printf("\n");
                break;
            }

            case LOAD:
                accumulator = memory[operand];
                break;

            case STORE:
                memory[operand] = accumulator;
                break;

            case ADD:
                accumulator += memory[operand];
                break;

            case SUBTRACT:
                accumulator -= memory[operand];
                break;

            case DIVIDE:
                if (memory[operand] == 0.0)
                {
                    fprintf(stderr, "*** ゼロで割ろうとしました ***\n");
                    printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);
                    return -1;
                }
                accumulator /= memory[operand];
                break;

            case MULTIPLY:
                accumulator *= memory[operand];
                break;

            case MOD:
                accumulator = fmod(accumulator, memory[operand]);
                break;

            case POWER:
                accumulator = pow(accumulator, memory[operand]);
                break;

            case BRANCH:
                instructionCounter = operand;
                break;

            case BRANCHENG:
                if (accumulator < 0.0)
                    instructionCounter = operand;
                break;

            case BRANCHZERO:
                if (accumulator == 0.0)
                    instructionCounter = operand;
                break;

            case HALT:
                endFlag = 1;
                printf("*** Simpletronは終了しました ***\n\n");
                printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);
                break;

            default:
                fprintf(stderr, "*** 不正な命令コードです ***\n");
                printDamp(accumulator, instructionCounter, instructionRegister, operationCode, operand, memory);
                return -1;
        }
    }

    return 0;
}

void printDamp(double accu, int instructionC, int instructionR, int operation, int operand, double m[])
{
    int i, j;

    printf("レジスタ:\n");
    printf("アキュムレータ     : %+f\n", accu);
    printf("命令カウンタ       : 0x%04X\n", instructionC);
    printf("命令レジスタ       : 0x%04X\n", instructionR);
    printf("命令コード         : 0x%02X\n", operation);
    printf("オペランド         : 0x%02X\n\n", operand);

    printf("メモリ:\n     ");
    for (i = 0; i < 10; i++)
        printf("  %8X ", i);
    printf("\n");

    for (i = 0; i < MEMORY_SIZE; i += 10)
    {
        printf("%04X ", i);
        for (j = i; j < i + 10; j++)
            printf("  %8.2f ", m[j]);
        printf("\n");
    }

    printf("\n文字列表示(ASCII):\n");
    for (i = 0; i < MEMORY_SIZE; i++)
    {
        if (m[i] >= 0 && m[i] <= 255)
        {
            char c = (char)((int)m[i]);
            if (isprint(c))
                printf("%04X: '%c'\n", i, c);
        }
    }
}
ポータルサイト
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?