前書き: 完全なコードは記事の最後に記載されていますが、前のコードは説明が簡単であるため、包括的なものではなく、参照のみを目的としています。
目次
1. バックギャモンゲームのルール
「私の友達は若い頃にバックギャモンをしたことがあると思います。それは 3行3 列のチェス盤にすぎません。ドロップする子がいない、つまり9 つのマスが占有されており、結果は引き分けになります。」
2. レイアウトの解析方法
コードを記述するにはきちんとした秩序あるデザインが必要であることはわかっていますが、スリームーン チェスのような非常に単純なゲームのデザインでさえ、わずか数十行のコードで完了できるものではありません。
以下の図に示すように、独自のヘッダー ファイル「game.h」を作成して、使用する必要があるヘッダー ファイルを一元的に保存し、使用する必要がある関数を宣言します。ソース ファイル内で独自のヘッダー ファイルを宣言するだけで済みます。#include "game.h"だけです。
さらに、必要な関数の作成に集中するために、新しいソース ファイルgame.cを作成します。
最後に、ゲームのメイン コードはソースファイルtest.cに記述されます。
3. コードの表示と説明
1. ゲームメニュー
どのゲームにも、ゲームのプレイ方法を選択するためのメニューが必要です。
void menu()//打印菜单函数
{
printf("******************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("******************************\n");
}
char board[ROW][COL] = {'0'};//游戏数组
int main()
{
int input = 0;
do {
menu();
printf("请选择->:");
scanf("%d", &input);//选择
switch (input)
{
case 1:
printf("三子棋\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
具体的にメニューを出力するメニュー(menu)関数 を作成し、do-whileループとswitch-case文を使ってゲームのループプレイを実現します。
ここにちょっとしたトリックがあります。while が 0 の判定条件はfalse で、ゼロ以外は true であることがわかっているので、 case 0 を終了ゲームとして使用し、ループを終了して1または他の数値を入力することもできます。 、ループが続き、選択を再開します。
2.チェス盤を表示する
私たちの理想的なチェス盤は次のようになります。これには明らかに2 次元配列が必要で、この 2 次元配列の要素はすべて" ", (space)です。
void SetBoard(char board[ROW][COL], int row, int col)//创建棋盘函数
{
int i;
int j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void ShowBoard(char board[ROW][COL],int row,int col)//展示棋盘函数
{
int i;
int j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j < col - 1)
printf("|");
}
printf("\n");
if(i < row - 1)
printf("---|---|---\n");
}
}
上記では、配列char board[ROW][COL] = {'0'}を定義しました。これは、要素「0」が 1 つだけある配列として定義されています。次に、上記の最初の関数 SetBoardを通じてチェス盤を作成します。チェス盤を装飾して表示するには、ShowBoard 関数を使用します。
3. プレイヤーはチェスをプレイします
void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋函数
{
while (1)
{
printf("玩家下棋(选择坐标):");
int x, y;
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("该坐标已被占用,请重新输入:\n");
}
else
printf("输入的坐标错误,请重新输入:\n");
}
}
ここでチェスをして、配列の要素を変更します。プレイヤーは座標を入力して、その位置が空かどうかを判断します。空の場合は、 '*'をドロップします。入力座標が範囲外の場合は、警告が発行されます入力が再入力されます。ここで、プレイヤーはチェスをプレイするときに 1 つのことに注意する必要があります。つまり、プレイヤーは必ずしもプログラマーである必要はありません。座標を選択するときに配列に対応する添字を入力しません。2行の場合は2 3になります。 3 つの列の場合、これら 2 つの数値を両方とも -1 にするだけで効果が得られます。
4. コンピューターチェス
void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋函数
{
printf("电脑下棋:\n");
int x, y;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
srand((unsigned int)time(NULL));//生成随机数,rand函数需要用,此处无用,供参考
コンピュータ チェスの重要なポイントの 1 つはランダム性です。ここでの座標はrand 関数を使用して乱数を生成する必要があります。コンピュータ自体はプレイヤーほどチェスに注意を払っていないことに注意してください。生成される乱数は0- 2 .コンピュータでチェスをプレイする場合、手は'#'であると規定します。
5.勝敗/引き分けの判定
int IsFull(char board[ROW][COL], int row, int col)//判断平局函数
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col) //判断输赢函数
{
int i;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] &&board[i][0] != ' ')
return board[i][0];
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];
if (IsFull(board, row, col))//判断平局
{
return 'Q';
}
return 'C';
}
ここでは勝敗を判定するIsWin関数を定義し、値を返すことで実現しています。
ゲームの進行状況を判断する方法として以下の4つを定めています。
プレイヤーの勝利 --> '*' を返します
コンピュータの勝利 --> '#' を返します
引き分け --> 'Q' を返します
ゲーム継続 --> 'C' を返します
なぜこれが規定されているのでしょうか? プレイヤーの駒が'*'であることがわかっており、プレイヤーが勝った場合、行、列、または対角線の 1 つが'*'になるため、自由に要素を返すことができ、次のものが返されます。コードはプレイヤーの勝利を実現できます。コンピューターも同じように勝ちます。同時に引き分けという結果も出てきますので、引き分けはどうですか?簡単に言うと、誰も勝たずにボードが埋まった場合、それは引き分けではないでしょうか?
そこで、配列が満杯かどうかを判断するIsFull 関数を定義し、満杯の場合は 1 を返し、最後の if判定ステートメントが true になるようにします。最後に'Q'を返し、満杯でない場合は 0 を返します。'C'を返します。
char ret = 0;//判断结果
case 1:
SetBoard(board, ROW, COL);//创建棋盘
ShowBoard(board, ROW, COL);//展示棋盘
while (1)
{
//玩家先开始下棋
PlayerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);//下棋之后展示棋盘
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑开始下棋
ComputerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);//下棋之后展示棋盘
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
break;
ここではメイン関数の判定を行い、 IsWin関数の戻り値を受け取るretを定義し、if -else判定文を使ってゲーム結果の判定を実現します。
4. フルコード表示
1.ゲーム.h
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3//行数为三
#define COL 3//列数为三
void SetBoard(char board[ROW][COL], int row, int col);//创建棋盘
void ShowBoard(char board[ROW][COL], int row, int col);//展示棋盘
void PlayerMove(char board[ROW][COL], int row, int col);//玩家下棋
void ComputerMove(char board[ROW][COL], int row, int col);//电脑下棋
char IsWin(char board[ROW][COL], int row, int col);//判断输赢
2.ゲーム.c
#include"game.h"
void SetBoard(char board[ROW][COL], int row, int col)//创建棋盘函数
{
int i;
int j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void ShowBoard(char board[ROW][COL],int row,int col)//展示棋盘函数
{
int i;
int j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j < col - 1)
printf("|");
}
printf("\n");
if(i < row - 1)
printf("---|---|---\n");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋函数
{
while (1)
{
printf("玩家下棋(选择坐标):");
int x, y;
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("该坐标已被占用,请重新输入:\n");
}
else
printf("输入的坐标错误,请重新输入:\n");
}
}
void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋函数
{
printf("电脑下棋:\n");
int x, y;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//玩家赢-->'*'
//电脑赢-->'#'
//平局-->'Q'
//游戏继续-->'C'
int IsFull(char board[ROW][COL], int row, int col)//判断平局函数
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col) //判断输赢函数
{
int i;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] &&board[i][0] != ' ')
return board[i][0];
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];
if (IsFull(board, row, col))//判断平局
{
return 'Q';
}
return 'C';
}
3.テスト.c
#include"game.h"
void menu()//打印菜单函数
{
printf("******************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("******************************\n");
}
char board[ROW][COL] = {'0'};//游戏数组
int main()
{
srand((unsigned int)time(NULL));//生成随机数,供电脑下棋使用
int input = 0;
char ret = 0;//判断结果
do {
menu();
printf("请选择->:");
scanf("%d", &input);//选择
switch (input)
{
case 1:
SetBoard(board, ROW, COL);//创建棋盘
ShowBoard(board, ROW, COL);//展示棋盘
while (1)
{
//玩家先开始下棋
PlayerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);//下棋之后展示棋盘
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑开始下棋
ComputerMove(board, ROW, COL);
ShowBoard(board, ROW, COL);//下棋之后展示棋盘
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
5. まとめ
3 つのチェスの作成もおそらくこれに当てはまります。ブログ主も初心者です。多くの場所で改善案があるかもしれません。今後は、コードを改善するために継続的に学習して自分自身を改善していきます。同時に、私の説明に対して、ご質問や改善点がございましたら、プライベート メッセージでお気軽にコメントしてください。
最後に、プログラミングが好きな私たちの小さなお友達がさらに先へ進んで、お気に入りのオファーを獲得できることを願っています。ブロガーの記事が気に入ったら、を 3 回クリックする ことを忘れないでください。また次回お会いしましょう!