三子棋小游戏————如何用C语言实现(含完整代码)
过程
https://live.csdn.net/v/embed/241852
QQ录屏20220925175438
整体思路(后面有思维导图,理清思维逻辑)
如何实现用C语言编写以上代码呢?其实并不难写,只是看起来比较繁琐罢了,但只要静下心来,把逻辑理顺,就能写出来,这对于新手小白来说是一个挑战,同时也是一个锻炼,那么如何能具体实现呢? 首先,我们为了能使自己的代码条理清晰,也方便自己以及他人日后查看,我们不能只写在一个源文件里,这样显得很繁琐。所以我们必须再创建一个源文件,用来存放被调用函数定义,同时,为了更加方便,我们再创建一个头文件,用来存放函数声明以及使用库函数时头文件的包含。然后在用来测试的源文件里着手写代码,首先要有一个菜单吧,供玩家选择,开始游戏,退出游戏等,然后我们要知道,我们最终的目的是在一个棋盘上进行游戏,既然是在棋盘上进行,就得有棋盘吧,所以我们要把一个棋盘用C语言写出来,写出来之后,我们还必须要有玩家和电脑来落子,否则怎么玩,既然落子,就会出现几种可能:1、玩家获胜。2、电脑获胜。3、平局(棋子满盘)。4、继续游戏(棋子未满盘)。
同时,我们可以把一个三子棋的棋盘看成是一个33的九宫格演变过来的,再仔细看,其实本质上是在一个二维数组里输入与#演变来的。知道这些,我们心里就有谱了,可以着手去写,完善细节。
实现过程
整理好之后开始入手:
#include"game.h"
//我们把函数声明,库函数头文件的包含都放在头文件game.h里,然后在测
//试源文件以及函数定义源文件里都包含一下,就可以实现跨文件使用
void menu()
{
printf("************************************\n");
printf("************************************\n");
printf("********* 1、play **********\n");
printf("********* 0、exit **********\n");
printf("************************************\n");
printf("************************************\n");
}
int main()
{
int input = 0;
//这是为了让电脑生成随机数使用的
srand((unsigned int)time(NULL));
do
{
//菜单
menu();
printf("请选择:>");
scanf("%d", &input);
//清理屏幕
system("cls");
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误,请重新输入“:>\n");
break;
}
} while (input);
return 0;
}
这里实现了我们菜单栏的打印,以及整体的一个轮廓,到这里,我们已经把退出游戏,以及错误返回给写好了,下面就着重入手游戏环节,game()的实现。
void game()
{
char ret = 0;
//二维数组的创建
char board[ROW][COL] = {0};
//初始化棋盘
init_board(board, ROW, COL);
//打印棋盘
display_board(board, ROW, COL);
//玩游戏环节
while (1)
{
//玩家下棋
player_move(board, ROW, COL);
//判断局面
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//打印棋盘
display_board(board, ROW, COL);
//电脑下棋
computer_move(board, ROW, COL);
//判断局面
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//打印棋盘
display_board(board, ROW, COL);
}
//我们自己规定,假如函数is_win(board, ROW, COL)返回值为*,表示玩家获胜
//假如函数is_win(board, ROW, COL)返回值为#,表示电脑获胜
//假如函数is_win(board, ROW, COL)返回值为C,表示继续游戏
//假如函数is_win(board, ROW, COL)返回值为Q,表示平局
if (ret == '*')
{
printf("-----------------------------------------------\n");
printf("------------ !!! VICTORY !!! --------------\n");
printf("-----------------------------------------------\n");
printf("----------- !!! 玩家获胜 !!! -----------\n");
printf("-----------------------------------------------\n");
}
else if (ret == '#')
{
printf("-----------------------------------------------\n");
printf("------------- !!! DEFEAT !!! --------------\n");
printf("-----------------------------------------------\n");
printf("----------- !!! 电脑获胜 !!! ----------\n");
printf("-----------------------------------------------\n");
}
else if (ret == 'Q')
{
printf("--------------------------------------------\n");
printf("--------------- !!!DRAW!!! ---------------\n");
printf("--------------------------------------------\n");
printf("----------- !!! 平局 !!! -----------\n");
printf("--------------------------------------------\n");
}
}
注意,这里我用的是ROW与COL来表示数组的行与列,这是为了以后万一我们要调整棋盘行列数,只需要在头文件修改数据就可以了,避免了把程序写死(只能是33棋盘) 大家注意看我头文件的内容:
很清晰明了的就可以看到里面的内容,用#define定义常量,这里就是三行三列,假如想要55的棋盘,只需要在这里修改ROW与COL的值就可以,很灵活。就像这样:避免了写死程序。
接下来就是这些函数的具体内容了,跟着思维导图,先看一下游戏前的准备:
void init_board(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 display_board(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)//第col-1列不打印|
{
printf("|");
}
}
//换行
printf("\n");
//最后一行不打印---|---|---
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
//最后的|不打印
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
这两个是使我们的棋盘最终定型所用的函数,由于我们要在数组里输入数据落子,同时为了保证美观性,所以我们必须保证二维数组里的所有数据都是空格,然后打印棋盘的时候不打印|与—|—|—我们进行了如上所改。最终才打印这种我们想要的棋盘:
有了棋盘接下来我们进行落子:
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家请落子:>\n");
while (1)
{
printf("请输入落子坐标:");
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] = '*';
//清理屏幕,每输出完后都清理历史痕迹
system("cls");
break;
}
else
{
printf("该位置已落子,请重新输入!\n");
}
}
else
{
printf("已超出棋盘范围,请重新落子!\n");
}
}
}
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑落子\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
//清理屏幕
break;
}
}
}
为了保证我们与电脑之间的下棋始终都在一个不变的棋盘上,我们使用了system()函数,每次落子都清理历史屏幕,这就使得我们像视频里那样,屏幕里始终只有一个棋盘。
落完子最后一步便是胜负的判定了:
int is_full(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 is_win(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][2] != ' ')
{
return board[i][2];
}
}
//列获胜的可能
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
{
return board[2][i];
}
}
//斜着获胜的可能
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[2][2];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] != ' ')
{
return board[2][0];
}
//平局可能
if (is_full(board,row,col) == 1)
{
return 'Q';
}
//继续游戏
return 'C';
}
上面,我们把所有取胜的结果全罗列了出来,那一行一列要么是*要么是#,所以我们直接返回它落的棋子,假如返回#,说明那一行或一列或斜着都是#。同时在这里我们又调用了一个函数,is_full()用来判断假如棋盘落子已满,将是平局。最后假如都不满足,就说明胜负未分,棋盘未满,游戏继续。
我们跟着逻辑走,把所有可能性想全,就可以保证我们写出来的代码又条理清楚,又可以完美运行。 到这里的时候,我们再进行调试,就发现可以很完美的进行游戏了。我们就可以奖励自己一顿大餐!再接再厉!!!
完整代码
测试源文件里的:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("************************************\n");
printf("************************************\n");
printf("********* 1、play **********\n");
printf("********* 0、exit **********\n");
printf("************************************\n");
printf("************************************\n");
}
void game()
{
char ret = 0;
//二维数组的创建
char board[ROW][COL] = {0};
//初始化棋盘
init_board(board, ROW, COL);
//打印棋盘
display_board(board, ROW, COL);
//玩游戏环节
while (1)
{
//玩家下棋
player_move(board, ROW, COL);
//判断局面
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//打印棋盘
display_board(board, ROW, COL);
//电脑下棋
computer_move(board, ROW, COL);
//判断局面
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//打印棋盘
display_board(board, ROW, COL);
}
//我们自己规定,假如函数is_win(board, ROW, COL)返回值为*,表示玩家获胜
//假如函数is_win(board, ROW, COL)返回值为#,表示电脑获胜
//假如函数is_win(board, ROW, COL)返回值为C,表示继续游戏
//假如函数is_win(board, ROW, COL)返回值为Q,表示平局
if (ret == '*')
{
printf("-----------------------------------------------\n");
printf("------------ !!! VICTORY !!! --------------\n");
printf("-----------------------------------------------\n");
printf("----------- !!! 玩家获胜 !!! -----------\n");
printf("-----------------------------------------------\n");
}
else if (ret == '#')
{
printf("-----------------------------------------------\n");
printf("------------- !!! DEFEAT !!! --------------\n");
printf("-----------------------------------------------\n");
printf("----------- !!! 电脑获胜 !!! ----------\n");
printf("-----------------------------------------------\n");
}
else if (ret == 'Q')
{
printf("--------------------------------------------\n");
printf("--------------- !!!DRAW!!! ---------------\n");
printf("--------------------------------------------\n");
printf("----------- !!! 平局 !!! -----------\n");
printf("--------------------------------------------\n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
//菜单
menu();
printf("请选择:>");
scanf("%d", &input);
//清理屏幕
system("cls");
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误,请重新输入“:>\n");
break;
}
} while (input);
return 0;
}
用来放函数定义的源文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//棋盘初始化
void init_board(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 display_board(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)//第col-1列不打印|
{
printf("|");
}
}
//换行
printf("\n");
//最后一行不打印---|---|---
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
//最后的|不打印
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家请落子:>\n");
while (1)
{
printf("请输入落子坐标:");
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] = '*';
//清理屏幕,每输出完后都清理历史痕迹
system("cls");
break;
}
else
{
printf("该位置已落子,请重新输入!\n");
}
}
else
{
printf("已超出棋盘范围,请重新落子!\n");
}
}
}
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑落子\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
system("cls");
//清理屏幕
break;
}
}
}
//满了返回1
//没满返回0
int is_full(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 is_win(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][2] != ' ')
{
return board[i][2];
}
}
//列获胜的可能
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
{
return board[2][i];
}
}
//斜着获胜的可能
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[2][2];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] != ' ')
{
return board[2][0];
}
//平局可能
if (is_full(board,row,col) == 1)
{
return 'Q';
}
//继续游戏
return 'C';
}
头文件
#pragma once
//printf函数所包含头文件
#include<stdio.h>
//rand函数所包含的头文件
#include<stdlib.h>
//时间戳,生成随机数使用
#include<time.h>
//清理屏幕,system()使用
#include<Windows.h>
#define ROW 3
#define COL 3
//棋盘初始化
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘
void display_board(char board[ROW][COL], int row, int col);
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);
//判断局面
char is_win(char board[ROW][COL], int row, int col);
望诸君加油!!!
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的