当前位置:网站首页>利用C语言巧妙实现棋类游戏——三子棋
利用C语言巧妙实现棋类游戏——三子棋
2022-07-29 06:49:00 【暴躁小程序猿】
小游戏:三子棋用C语言实现

你是否学完了C语言的函数、数组、选择结构、循环结构苦于没有实战小项目巩固自己所学的知识呢,今天小程序猿就给大家带来了一个游戏的小游戏——三子棋,利用C语言实现的,希望对大家能有所帮助。
我们大家大多都接触过棋类游戏,最常见的就是五子棋啦,今天我们简化游戏,只涉及到三子棋,两者思路是相同的,如果大家有兴趣在可以在接下来的思路上尝试实现五子棋。
一、游戏规则:
三字棋的规则如下:我们这里只谈论三子棋,依照这个思路也可以实现五子棋等多种棋类游戏 三子棋规则如下:游戏人和电脑轮流下棋,谁先让自己的三颗棋子连成一条直线获胜,如果棋盘下满则双方平局。
二、实现的思路
提到三子棋就必须要有棋盘,棋盘可以用一个二维数组来实现,因为我们将来数组所存储的内容将是我们的棋子,所以我们定义一个char型数组,下棋的位置可以输入坐标来决定,如果几个坐标对应数组元素的内容一样就表示哪一方获胜,其中涉及了选择分支语句和循环语句,具体实现如下:
三、代码讲解
1.头文件
头文件我们命名为game.h
众所周知,头文件中存放的内容是函数的声明,涉及到的库函数以及宏定义;
我所编写的头文件如下:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.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);
这里唯一要注意的就是在宏定义#define ROW 3 后面一定没有分号。
2.调试部分
我们将主函数放在调试部分,命名给test.c,主要是程序的框架,不包含游戏主要功能的具体实现;
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#include "game.h"
void menu()
{
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\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);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
display_board(board, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
既然是游戏就应该有菜单可供玩家选择,我们简单设计一个菜单;菜单只需要打印内容即可,所以菜单函数设计成void即可;
菜单模块如下;
void menu()
{
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("*********************************\n");
}
游戏部分直接调用我们设计的函数,假设玩家棋子是*,电脑棋子是#,r变量ret表示游戏的进程,*表示玩家获胜,#表示电脑获胜,Q表示平局,c表示游戏继续;
代码如下:
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);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("玩家获胜\n");
}
else if (ret == '#')
{
printf("电脑获胜\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
display_board(board, ROW, COL);
}
3.游戏功能的具体实现
游戏功能涉及到棋盘的初始化,棋盘的打印,玩家下棋,电脑下棋,棋盘是否占满的判断,游戏结果的判断六大功能,下面分模块进行讲解:
1.棋盘的初始化
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] = ' ';
}
}
}
此处利用一个二维数组char board[ ][ ]实现对棋盘位置的存储,利用循环将每一个位置都初始化为空格。
2.棋盘的打印
void display_board(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++)
{
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");
}
}
}
此处将棋盘按照一种标准格式打印,利用循环打印出棋盘的轮廓,
效果图如下:

3.玩家下棋
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] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
}
玩家下棋的功能就是利用x和y两个变量作为数组的下标,将对应数组的内容替换成玩家的棋子,同时玩家不能在已经有棋子的地方下棋,所以利用了判断语句,判断对应数组存放的内容是否是空格,如果是空格则表示可以在此处下棋,否则就表示坐标被占用了请玩家重新输入,同时如果输入的下标导致数组越界就提示坐标非法,重新输入。
4.电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
//0~32726
//%3-->0~2
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
电脑下棋我们采用rand函数,但是rand函数使用前要定义一个随机入口,就必须用到srand函数,srand函数参数要是一个无符号整型数据,我们用时间戳来作为它的参数,rand函数随机生成0~32726之间的数据,我们对rand函数取模%,就可以让变量x和y的范围锁定在0 ~2之间,如果数组对应的内容为空格则表示可以下棋,用#替换数组的内容。
5.棋盘是否占满的判断
static 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;
}
此处简单利用循环判断,如果棋盘满了,返回1,不满,返回0
6.结果的判断
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][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 (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
如果每一行每一列或者两个对角线上的元素都相同则表示一方获胜,如果都没有则表示平局,棋盘没有下满游戏继续。
7.游戏功能实现部分完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#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;
for (i = 0; i < row; i++)
{
int j = 0;
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 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] = '*';
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] = '#';
break;
}
}
}
static 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][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 (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
以上便是三子棋所有功能实现的思路以及代码,希望对大家有所帮助,欢迎大家随时私信,如果对大家有帮助的话可以关注加三连,以后可以互相学习进步~
边栏推荐
- Remote invocation of microservices
- Excel文件读写(创建与解析)
- 如何使用gs_expansion扩展节点
- Interface test actual project 03: execute test cases
- 作业7.28 文件IO与标准IO
- After three years of outsourcing, the salary of automatic testing after job hopping is twice that of the original. The secret is
- CAN&CANFD综合测试分析软件LKMaster与PCAN-Explorer 6分析软件的优势对比
- SpingBoot整合Quartz框架实现动态定时任务(支持实时增删改查任务)
- MySQL - multi table query
- MySQL----多表查询
猜你喜欢

win11VMware打开虚拟机就蓝屏重启以及启动不了的解决方案

Cvpr2021 | multi view stereo matching based on self supervised learning (cvpr2021)

MySQL advanced (Advanced) SQL statement (I)

使用VsCode配置MySQL实现连接、查询、等功能

JS chicken laying eggs and egg laying chickens. Who appeared earlier, object or function? Is function an instance of function?

做开发4年13K,想转行自动化测试,薪资还能涨吗···

VMware16安装虚拟机遇到的问题

Implementation of book borrowing management system based on C language

win11系统错误:由于找不到 iertutil.dll,无法继续执行代码。重新安装程序可能会解决此问题

MySQL - multi table query
随机推荐
我的个人网站不让接入微信登录,于是我做了这个
fillder使用
When NPM is installed, it is stuck. There are five solutions
Variables and encryption in ansible
要不要满足客户所有的需求
时钟树综合(一)
20-40k | mecarmand 3D vision algorithm / software / Product Manager Recruitment
后缀自动机(SAM)讲解 + Luogu p3804【模板】后缀自动机 (SAM)
Gin service exit
怎么会不喜欢呢,CICD中轻松发送邮件
JS 鸡生蛋与蛋生鸡问题,Object与Function究竟谁出现的更早?Function算不算Function的实例?
MySQL 使用客户端以及SELECT 方式查看 BLOB 类型字段内容总结
数组的子集能否累加出K
0 8 动态规划(Dynamic Programming)
个人博客系统(附源码)
LeetCode 879. 盈利计划
Gin parameter validation
Gin template
MVFuseNet:Improving End-to-End Object Detection and Motion Forecasting through Multi-View Fusion of
MySQL - multi table query