当前位置:网站首页>【三子棋】C语言实现简易三子棋
【三子棋】C语言实现简易三子棋
2022-08-01 23:52:00 【即盎】
前两天新学了数组以及它的简单应用——三子棋,这里,便将它用博客的形式写出来,复习巩固的同时也希望能够帮到你们。
文章目录
一、项目要求
应用二维数组完成三子棋,实现其各种功能。
二、项目功能的实现
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] = ' ';
}
}
}
打印棋盘时,我们可以将整个棋盘分解为数据行与分隔行,并将一行数据行与一行分隔行作为一组,根据想要的效果限制条件进行循环打印。而在一行数据行中,我们有可以将一个数据与一个分隔号 ‘|’ 作为一组,同样限制条件进行循环打印。
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)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
2.玩家下棋
开始游戏后,先由玩家下棋。
玩家输入要下的坐标(x,y),先判断坐标的合法性(是否在棋盘的范围内),合法后,再判断该坐标是否已被占用,若没有,则落子 ‘*’。
值得注意的是,由于玩家的思维,棋盘的行、列都是从1开始,因此,我们判断合法性时,x范围应在1~ROW(最大行),y范围应在1 ~ COL(最大列),而判断坐标是否被占用时,应判断x-1,y-1。
void player_game(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请玩家下棋!\n");
printf("请输入要下的坐标:");
//判断输入坐标是否正确
while (1)
{
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("该坐标已被占用,请重新输入:");
}
}
else
{
printf("该坐标不符合规则,请重新输入:");
}
}
}
3.电脑下棋
玩家下棋后,再由电脑产生随机数x,y进行下棋操作。
利用rand()函数产生随机数,要保证产生的x,y合法,只需要将产生的随机数分别取row,col的余数即可,这样,得到的x,y范围始终在0~row-1,0 ~ col-1。得到x,y的值后,再判断该坐标是否被占用,若没有,则落子 ‘#’。
在这里,由于是电脑下棋,因此,若产生的坐标已被占用,不必显示在屏幕上,直接再重新产生随机数即可。
void computer_game(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.判断游戏状态
在这个程序中,最复杂的部分应该就是判断输赢了。我们可以将游戏状态分为4种:
’ * '——玩家赢;
’ # '——电脑赢
’ Q '——平局
’ C '——游戏继续
若有赢家,则赢的情况有三种:行、列、对角线。通过判断这三种情况并返回符合其中一种情况的任意数据,我们便可以得出赢家。
若平局,即棋盘已满,但仍无赢家,则每一次下棋后我们可以先判断是否有赢家,若没有,再判断棋盘是否已满,若棋盘已满,则为平局,返回’ Q '。
若无赢家,棋盘也未满,则返回’ C ',开始下一轮下棋。
//判断棋盘是否已满
int full_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++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char is_win(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] == board[i][(j + 1)%3] && board[i][(j + 1) % 3] == board[i][(j + 2) % 3] && board[i][j] != ' ')
return board[i][0];
}
}
//列
for (j = 0; j < col; j++)
{
for (i = 0; i < row; i++)
{
if (board[i][j] == board[(i + 1)%3][j] && board[(i + 1) % 3][j] == board[(i + 2) % 3][j] && board[i][j] != ' ')
return board[i][j];
}
}
//主对角线
for (i = 0; i < row; i++)
{
if (board[i][i] == board[(i + 1) % 3][(i + 1) % 3] && board[(i + 1) % 3][(i + 1) % 3] == board[(i + 2) % 3][(i + 2) % 3] && board[i][i] != ' ')
return board[i][i];
}
//副对角线
for (i = 0; i < row - 2; i++)
{
for (j = col - 1; j >= 0; j--)
{
if (board[i][j] == board[(i + 1)%3][j - 1] && board[(i + 1)%3][j - 1] == board[(i + 2)%3][j - 2] && board[i][j] != ' ')
return board[i][j];
}
}
if (1 == full_board(board, row, col))
{
return 'Q';
}
return 'C';
}
三、项目演示
1.棋盘的打印

2.玩家下棋

3.电脑下棋

4.输/赢判定

四、代码展示
1.game.h
#pragma once
#include <stdio.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_game(char board[ROW][COL], int row, int col);
//电脑下棋
void computer_game(char board[ROW][COL], int row, int col);
//判断游戏状态
char is_win(char board[ROW][COL], int row, int col);
2.game.c
#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)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
void player_game(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请玩家下棋!\n");
printf("请输入要下的坐标:");
//判断输入坐标是否正确
while (1)
{
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("该坐标已被占用,请重新输入:");
}
}
else
{
printf("该坐标不符合规则,请重新输入:");
}
}
}
void computer_game(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 full_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++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char is_win(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] == board[i][(j + 1)%3] && board[i][(j + 1) % 3] == board[i][(j + 2) % 3] && board[i][j] != ' ')
return board[i][0];
}
}
//列
for (j = 0; j < col; j++)
{
for (i = 0; i < row; i++)
{
if (board[i][j] == board[(i + 1)%3][j] && board[(i + 1) % 3][j] == board[(i + 2) % 3][j] && board[i][j] != ' ')
return board[i][j];
}
}
//主对角线
for (i = 0; i < row; i++)
{
if (board[i][i] == board[(i + 1) % 3][(i + 1) % 3] && board[(i + 1) % 3][(i + 1) % 3] == board[(i + 2) % 3][(i + 2) % 3] && board[i][i] != ' ')
return board[i][i];
}
//副对角线
for (i = 0; i < row - 2; i++)
{
for (j = col - 1; j >= 0; j--)
{
if (board[i][j] == board[(i + 1)%3][j - 1] && board[(i + 1)%3][j - 1] == board[(i + 2)%3][j - 2] && board[i][j] != ' ')
return board[i][j];
}
}
if (1 == full_board(board, row, col))
{
return 'Q';
}
return 'C';
}
3.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("********************************\n");
printf("******* 1.PLAY *********\n");
printf("******* 0.EXIT *********\n");
printf("********************************\n");
}
//玩家赢——‘*’
//电脑赢——‘#’
//平局 ——‘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_game(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_game(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");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
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;
}
五、总结
本次项目的代码不算困难,重要的是逻辑顺序,尤其是判定输赢那一部分。只要搞清楚了逻辑,代码写下来总体还是比较顺畅。
大家看到如果有什么不懂的地方,都可以评论或者私信问我。如果有哪些地方写得不对,也希望大家能够不吝赐教!

边栏推荐
猜你喜欢

工件SSMwar exploded 部署工件时出错。请参阅服务器日志了解详细信息

在CDH的hue上的oozie出现,提交 Coordinator My Schedule 时出错

深度学习基础-基于Numpy的循环神经网络(RNN)实现和反向传播训练

async和await用法介绍

EasyExcel的简单读取操作

The monthly salary of the test post is 5-9k, how to increase the salary to 25k?

Use Jenkins for continuous integration, this knowledge point must be mastered

thinkphp漏洞总结

架构基本概念和架构本质

在MySQL中使用MD5加密【入门体验】
随机推荐
如何进行数据库备份
【Leetcode】473. Matchsticks to Square
在CDH的hue上的oozie出现,提交 Coordinator My Schedule 时出错
【Leetcode】2360. Longest Cycle in a Graph
The third chapter of the imitation cattle network project: develop the core functions of the community (detailed steps and ideas)
带你搞懂MySQL隔离级别,两个事务同时操作同一行数据会怎样?
Spark Sql之join on and和where
yay 报错 response decoding failed: invalid character ‘<‘ looking for beginning of value;
Flink学习第五天——Flink可视化控制台依赖配置和界面介绍
中职网络安全竞赛B7比赛部署流程
Loading configuration of Nacos configuration center
6132. All the elements in the array is equal to zero - quick sort method
很多人喜欢用多御安全浏览器,竟是因为这些原因
机器学习文本分类
在CentOS下安装MySQL
asyncawait和promise的区别
Excel文件读写(创建与解析)
Docker实践经验:Docker 上部署 mysql8 主从复制
ICLR 2022最佳论文:基于对比消歧的偏标签学习
【MySQL系列】MySQL索引事务