三子棋游戏——C语言
大家好,今天给大家带来的是用C语言实现“三子棋游戏”的代码编写。
手把手教学,包教包会,童叟无欺哦~
若有不足或疑问,欢迎评论区指正交流。
我是黎明_CL,接下来我们进入主题。
创建文件
准备:
- 首先打开编译器,创建工程。
- 为了方便编写和管理,我们创建三个文件,分别如下:
-
头文件game.h
- 用来存放数与函数的声明,便于直观地阅读代码
- 注:以下所有游戏函数的声明都放在该文件中
-
game.c
- #include "game.h"引用头文件
- 用来定义函数,存放函数实现的具体内容
- 注:以下所有游戏定义都放在该文件中
-
创建test.c文件,用来游戏的调试
- main函数
- #include "game.h"引用头文件
`
//test.c
#include “game.h”
//#include <stdio.h>在头文件中声明,此处只声明头文件即可
int mian()
{
return 0;
}
`C
接下来让我为大家带来三子棋游戏内容的实现过程
-
游戏
用一个简单的printf函数打印菜单mune。
- 当玩家键盘输入input为1时开始游戏,进入游戏部分,所以我们进入game()函数;
- 输入input为0退出游戏;
- 输入input为其它数字,退出游戏;
- (使用switch语句多语句判断。为了使玩家玩多次,使用do…while循环
。)
代码如下:
int mian()
{
do
{
manu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:>\n");
break;
}
} while (input==1);
return 0;
}
游戏主体
- 分析棋盘,我们发现可以采用二维数组board[3][3]来表示棋盘。但为了使程序可被复用,便于更改数据,扩展游戏,我们在头文件内定义宏COL与ROW来表示棋盘的行和列。
#define ROW 3 //行
#define COL 3 //列
1.初始化棋盘
- 游戏刚开始时,要使棋盘中数据为空格字符’ '。所以要对数组board[ ROW ][COL]进行初始化。
初始化棋盘InPut(board,ROW,COL);
//game.c
void InPut(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] =' ';
}
}
}
2.打印棋盘
- 这时我们尝试打印棋盘,发现看不见棋盘,因为数组是空格。所以我们要在屏幕上打印分割线来显示棋盘。所以数字间用分割线来显示,定义显示棋盘函数void DisplayBoard(char board[ROW][COL], int row, int col)
- 打印数据
- 打印分割行
效果如下:
int i = 0;
for (i = 0; i < row; i++)
{
//1.打印数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //数据
if (j < col - 1)
printf("|"); //分隔线
}
printf("\n");
//2.打印分割行
if (i < col - 1)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf("---");
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
}
3.玩家/电脑下棋
目标:
- 接下来【玩家下棋】,定义函数void PlayerMove(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col)
{
while(1)
{
printf("请输入坐标:>\n");
printf("输入行号列号,中间用空格隔开:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
//判断输入行列号是否符合数量
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断该行是否已经落子
if (board[x - 1][y - 1] == ' ') //玩家不是程序员,而数组是从0开始,故减去1;
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("该位置已落子,请重新输入\n");
}
else
printf("坐标错误,请重新输入\n");
}
}
- 接下来【电脑下棋】,定义函数void ComputerMove(char board[ROW][COL], int row, int col);
- 要求:随机输入
- 调用rand()函数产生随机数,在头文件中包含#include <stdlib.h>
- 在main函数中调用srand((int)time(NULL) 来生成时间戳,在头文件中包含#include <time.h>
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
4.判断输赢
- 定义char IsWin(char board[ROW][COL], int row, int col);函数在玩家和电脑每次下完后都来判断输赢,故使用while循环;
- 通过返回字符判断,规则如下:
- 结束游戏·
- 玩家赢 ‘*’
- 玩家输 ‘#’
- 平局 ‘Q’ 如果棋盘满了,则平局
- 继续游戏 ‘C’
- 结束游戏·
- 为简化判断,每次下完都有【继续游戏】或【结束游戏】两种结果,所以在主函数中判断是否继续;
- 即若返回’C’则继续游戏;
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][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[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][2] && board[1][2] == board[2][0] && board[0][2] != ' ')
return board[0][2];
//如果棋盘满了,则平局,所以判断棋盘是否放满。
//故定义函数int IsFull(char board[ROW][COL],int row,int col)
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
return 'C';
}
int IsFull(char board[ROW][COL],int row,int col)
{
//遍历每个元素,判断是否为空格。但凡有一个空格没放,则返回0;
//若没空格,则表示棋盘都满了,返回1;
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] ==' ')
{
return 0;
}
}
}
return 1;
}
- 如果结束游戏,则在main函数中跳出循环,进行输赢判断`
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
代码
//game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3 //行
#define COL 3 //列
//打印菜单
void manu();
//初始化菜单
void InPut(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);
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game()
{
char board[ROW][COL] = { 0 };
//初始化棋盘
InPut(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");
}
int main()
{
srand((unsigned int)time(NULL));
//打印菜单
int input = 0;//注意放在while循环外面
do
{
manu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏\n");
game();
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"
void manu()
{
printf("***********************\n");
printf("****** 1. Play ******\n");
printf("****** 0. Exit ******\n");
printf("***********************\n");
}
void InPut(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] =' ';
}
}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//1.打印数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //数据
if (j < col - 1)
printf("|"); //分隔线
}
printf("\n");
//2.打印分割行
if (i < col - 1)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf("---");
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
while(1)
{
printf("请输入坐标:>\n");
printf("输入行号列号,中间用空格隔开:>");
int x = 0;
int y = 0;
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)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int IsFull(char board[ROW][COL],int row,int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
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][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[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][2] && board[1][2] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
return 'C';
// 玩家赢 '*'
//玩家输 '#'
//平局 'Q'
//继续 'C'
}
写在最后
- 以上即为这个游戏所有详细操作及解释,当然还有可优化的地方如下;
- 优化
- 在game.c中判断时代码不具有很强的复用性,可在后期进行改进优化
//判断输赢
char IsWin(char board[ROW][COL], int row, int col) - 在界面上可以采用图形库,,让游戏界面更美观
感谢阅读!创作不易,如果觉得其中一点有帮助到您,还请关注我,一起进步。
当然来一个点赞也是可以的哦!
🚀Live long and Prosper!🖖🏼
- 在game.c中判断时代码不具有很强的复用性,可在后期进行改进优化
- 优化