目录
整体思路:(test .c)(game .h)(game .c )
三子棋就是俗话所说的井字棋。
对于初学者来说完整的写出三子棋代码还是相对较难的,而且代码的长度相对较长,此时我们便可以分成各函数最后引用其到主函数中来实现代码的运行,首先整体的思路要确立完整。
整体思路:(test .c)(game .h)(game .c )
我们可先将三子棋拆分成3份源文件来使代码整体的观感更简洁明了
test .c 测试游戏的逻辑
game .h 关于游戏相关函数的申明,符号申明头文件的包含
game .c 游戏相关函数的实现
第一步:(游戏开始界面)
我们得创建三子棋的开始界面,我们先可写一个菜单函数。以玩家输入的值1或0来判断游戏的开始或结束,同时也要考虑玩家输入1和0之外的数,打印提醒玩家重新输入1或0这两个数字,我们可以便由此联想到循环语句和 switch 语句来实现可重复玩三子棋和对玩家选择的判断。
teset.c 中初始界面函数代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
printf("************************************\n");
printf("***** 1. play *******\n");
printf("***** 0. exit *******\n");
printf("************************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择");
scanf("%d", & input);
switch (input)
{
case 1:
game();
printf("三子棋游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重选择\n");
break;
}
}
while (input);
return 0;
}
结果如下:
第二步:(棋盘的初始化和打印)
我们得实现三子棋游戏,而不仅仅只是一句话。我们可写一个game()函数,而三子棋游戏的开始便是棋盘的打印,棋盘的打印我们又可分为几小类
a:明确棋盘是一个二维数组,且类型为字符数组(定义玩家下的棋子" * ",电脑下的棋子为"#",开始的空棋盘中存放的为" " (空格))。
b:我们虽知三子棋的棋盘为3*3的网格,但我们可将 行和列 用被定义的常量代替,我们只需将定义的常量的值修改,从而可以很轻松的修改该棋盘的 行和列 。(全局观意识)
如图:
c:我们此时便需要初始化三子棋棋盘,我们可创建一个 Initboar(board,ROW,COL) 函数,在game.h中申明,在game.c中写出该函数,在tset.c中引用,最后来完成我们棋盘的初始化。
game.c中的 Initboar(board,ROW,COL) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
//初始化棋盘 初始化空格 我们可放到game.c 中
void Initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board [i] [j] = ' ' ;
}
}
}
d:我们要打印我们的棋盘,其本质就是打印数组的内容。
我们再创建一个DisplayBoard(board,ROW,COL) 函数,在game.h中申明,在game.c中写出该函数,在tset.c中引用。棋盘我们可对其进行拆分为多块依次循环打印。
如图:(红色为一块,绿色为一块)
game.c中的 DisplayBoard(board,ROW,COL) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
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)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col-1)
{
printf("|");
}
}
}
printf("\n");
}
}
结果为:
第三步:(玩家下棋和电脑下棋的打印)
我们得在 game() 函数中来实现我们玩家下棋之后电脑再下棋的这么一个步骤。
我们也可再细分为几小类
a: 先是玩家下棋的函数,我们可创建一个 playerMove(board, ROW, COL) 函数在game.h中申明,在game.c中写出该函数,在tset.c中引用。
b: 我们再写此函数开始前,再细分,先是我们要判断玩家输入的坐标是否合法,再而我们要判断玩家所下坐标是否被占用,最后下棋成功后跳出该循环。
game.c中的 playerMove(board, ROW, COL) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf ("玩家走\n");
//判断坐标合法性
while (1)
{
printf("请输入下棋的坐标\n");
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");
}
}
}
c: 完成该函数后需加上前 DisplayBoard(board, ROW, COL) 函数(打印函数)将玩家所下的棋打印到井字格中。
d:接下来便是电脑下棋的函数,我们可创建一个 computerMove(board, ROW, COL) 函数在game.h中申明,在game.c中写出该函数,在tset.c中引用。
e: 电脑下棋是随机下的,从而我们便需要利用 时间 来完成随机数的生成,同时我们电脑所下的坐标应在井字棋盘内,所以我们可以分别用 行和列 来取其随机数的模,从而完成随机坐标的生成。
game.c中的 playerMove(board, ROW, COL) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
void computerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走\n");
// srand((unsigned)time(NULL)) 随机值的生产,我们将其放入 test.c 主函数中
// 生产随机值所需引用的两个头文件
// #include<stdlib.h>
// #include<time.h>
while (1)
{
int x = rand() % row;
int y = rand() % col;
//判断占用
if (board[x][y] == ' ');
{
board[x][y] = '#';
break;
}
}
}
f:完成该函数后需加上前 DisplayBoard(board, ROW, COL) 函数(打印函数)将电脑所下的棋打印到井字格中。
结果为:
第四步:(游戏输赢和平局的判断)
我们便需要判断是玩家赢得游戏还是电脑赢得游戏或者是否平局,如果这三种情况都未出现则游戏继续。
a: 我们可先创建一个 char IsWin() 函数在game.h中申明,在game.c中写出该函数,在tset.c中引用。以返回值来判断游戏的状态。
(玩家赢“ * ” 电脑赢 “# ” 平局“ Q ” 游戏继续“ C ”)
其中对赢游戏的判定条件分为以下四种:
1 :三个位于同行 2:三个位于同列 3:三个位于同一条对角线 4:平局
game.c中的 playerMove(board, ROW, COL) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
// 判断三个位于同行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断三个位于同列
for (i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][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];
}
//判断平局
//如果棋盘满了返回1,不满返回0
int ret = IsFull(board, row, col); //创建判断棋盘是否满了的函数(平局)
if (ret == 1)
{
return 'Q'; //返回 Q 为棋盘已满 玩家电脑平局
}
return 'C'; // 返回 C 为棋盘未满 游戏继续
b:在判断是否平局的问题上,我们可创建 IsFull(board, row, col) 函数,直接写在 game.c 中被playerMove(board, ROW, COL) 函数所引用。
判断是否平局,实质上就是对我们的二维数组棋盘进行查找,看是否存在 ' ' (空格),如果存在即棋盘未满,反之则棋盘已满且未决出胜负为平局。
game.c中的 IsFull(board, row, col) 函数:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;//棋盘没满
}
}
}
return 1;
}
c:我们需要对 test.c 中的 game() 函数进行我们判断输赢函数的引用,并使用分支语句判断 ret 的返回字符,进而可判断是电脑还是玩家赢得游戏又或是平局。
到此我们三子棋游戏的制作就完全结束了,以下是各文件的所有代码段汇总
test .c 测试游戏的逻辑
game .h 关于游戏相关函数的申明,符号申明头文件的包含
game .c 游戏相关函数的实现
test .c 文件代码汇总:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include"game.h"
void menu()
{
printf("************************************\n");
printf("***** 1. play *******\n");
printf("***** 0. exit *******\n");
printf("************************************\n");
}
void game()
{
char board[ROW][COL]; // 二维数组 储存数据
Initboard(board, ROW, COL); //初始化棋盘 初始化空格
DisplayBoard(board, ROW, COL);//打印棋盘
char ret = 0;
while (1)
{
//玩家下棋
playerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
computerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断电脑是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL); //重新开始打印棋盘 开始新的游戏
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择");
scanf("%d", & input);
switch (input)
{
case 1:
game();
printf("三子棋游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重选择\n");
break;
}
}
while (input);
return 0;
}
game .c 文件代码汇总:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include <stdio.h>
//初始化棋盘 初始化空格 我们可放到game.c 中
void Initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
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)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col-1)
{
printf("|");
}
}
}
printf("\n");
}
}
//玩家下棋的函数
void playerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf ("玩家走\n");
//判断坐标合法性
while (1)
{
printf("请输入下棋的坐标\n");
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");
// srand((unsigned)time(NULL)) 随机值的生产,我们将其放入 test.c 主函数中
// 生产随机值所需引用的两个头文件
// #include<stdlib.h>
// #include<time.h>
while (1)
{
int x = rand() % row;
int y = rand() % col;
//判断占用
if (board[x][y] == ' ');
{
board[x][y] = '#';
break;
}
}
}
// 判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
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 = 0;
// 判断三个位于同行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断三个位于同列
for (i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][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];
}
//判断平局
//如果棋盘满了返回1,不满返回0
int ret = IsFull(board, row, col); //创建判断棋盘是否满了的函数(平局)
if (ret == 1)
{
return 'Q'; //返回 Q 为棋盘已满 玩家电脑平局
}
return 'C'; // 返回 C 为棋盘未满 游戏继续
}
game .h 文件代码汇总:
#pragma once
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
// 该定义我们可放到 game.h 头文件中
// 再在此 test.c 中引用 #include"game.h",即可运用我们自己定义的头文件
// 函数的申明 ,我们可放到 game.h 头文件中
void Initboard(char board[ROW][COL], int row, int col);
void DisplayBoard(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);
试玩:
以上便是关于三子棋(井字棋)的内容了,喜欢可点个赞或收藏哦!
谢谢浏览!(如有问题,请各位大神即使指出,我会及时纠正!)