关键词:
Linux操作系统项目实战——五子棋
GIF:
目录
后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教! ——By 作者:新晓·故知
一、问题导引:
在进行Linux入门学习后,通过运用Linux环境指令操作、Vim编辑器、学习五子棋的基本原理等,进行Linux环境下的简单的五子棋项目实现。
生活中的五子棋:
从上图可以看出,五子棋(这类棋)有先手、后手之分(当然也有禁手、俗手、妙手等),这里只进行简单的交互式、窗口化项目实现。(上图涉及GUI技术、图像渲染技术等,太过高深)
二、实现要求:
熟悉Linux环境指令操作
Linux中相关开发工具的基本使用
熟悉在Linux环境当中进行C编程
掌握五子棋的基本原理
编写五子棋程序的上层基本调用框架
等等
说明:本篇博客采用VMware Workstation 16+CentOS7作为实现演示示例工具
三、五子棋原理:
1.落子数据信息保存载体:
需要记录每个玩家的落子位置,用来判断谁赢谁输。
可采用二维数组保存棋盘信息,棋盘上面的任何一个位置,里面可以放置三类信息:
空(没有落子)
玩家1的落子(黑子)
玩家2的落子(白子)
2.落子思路:
1.如果下一步能赢,就走这一步
2.如果下一步会输,就阻止对方赢
3.统计棋子数决定在哪里落子。
其中 阻止对方赢,就是在对方能赢的点上落子,一般会有1到3个点。
3.判断“五子连珠”
下棋就是在二维数组中找对应的空位置,进行落子
落完子之后下来就要考虑该落子位置是否有”五子连珠“,进而进行输赢判定,每一次走棋,多会有四种情况:
玩家1获胜
玩家2获胜
平局(棋盘满了等)
未出结果(游戏继续)其中,“未出结果”游戏要继续,其他三种情况,游戏不用继续
四、项目实现步骤:
Ⅰ.创建目录及文件:
1.在Linux环境下创建名为Gobang的文件目录:
mkdir Gobang
(目录名随意,这里采用五子棋的英文命名目录)
2.创建多文本编辑:
touch Makefile
3.分别创建子文件:
touch game.h touch game.c touch main.c
Ⅱ、输入Linux环境指令进入目录及文件:
Ⅲ、Linux环境编程实现:
1.顶层逻辑设计:
输入Linux指令:
(1)
vim Makefile
(2)
vim game.h
(3)
vim game.c
(4)
vim main.c
2.模块化设计:
第一步. main构建游戏起始逻辑 第二步 . 构建游戏入口 Game() 函数 第三步 . 编写核心函数,定义全局游戏信息 第四步 . 编写 Makefifile ,完成第一步项目构建 第五步 . 实现游戏落子逻辑 第六步 . 实现游戏的显示逻辑 第七步 . 判定五子连珠然后判定游戏结果3.联动模块组合封装:
完整代码:
(1)game.c
#include "game.h" /*说明: 1.定义全局变量,保证代码逻辑尽可能简化,传参不那么复杂 2.代表玩家输入位置的最近的位置下标 3.不是说一定要定义成全局变量,而是为了减少传参等,降低复杂度*/ int x = 0; int y = 0; //按照x,y作为起点,按照特定的方向,求连续相对的最大格式 int ChessCount(int board[][COL], int row, int col, enum Dir d) int _x = x - 1; //棋盘行标从1开始 int _y = y - 1; //棋盘列标从1开始 //统计以当前棋子为起始位置8个方向的棋子数 int count = 0; while (1) switch (d) case LEFT: _y--; break; case RIGHT: _y++; break; case UP: _x--; break; case DOWN: _x++; break; case LEFT_UP: _x--, _y--; break; case LEFT_DOWN: _x++, _y--; break; case RIGHT_UP: _x--, _y++; break; case RIGHT_DOWN: _x++, _y++; break; default: //Do Nothing break; //坐标移动完成,一定要先保证没有越界 if (_x < 0 || _x > row - 1 || _y < 0 || _y > col - 1) break; //合法 //判断指定位置和原始位置的棋子是否相同,“连珠”就体现在这里 if (board[x - 1][y - 1] == board[_x][_y]) count++; else break; return count; /*说明:IsOver的返回值有4种情况 1.NEXT:表明要继续 2.PLAYER1_WIN: 玩家1获胜 3.PLAYER2_WIN:玩家2获胜 4.DRAW: 平局*/ int IsOver(int board[][COL], int row, int col) /*棋子统计逻辑 1.以落子位置作为起点,进行8个方向的相同玩家方棋子统计 落子位置下标与方向统计有很强的关联性 2.当玩家2落子,说明玩家1没有赢,因此需要先走一步就先判断一次,走到当前才有可能赢 3.+1是统计被忽略的当前落子*/ int count1 = ChessCount(board, row, col, LEFT) + ChessCount(board, row, col, RIGHT) + 1; int count2 = ChessCount(board, row, col, UP) + ChessCount(board, row, col, DOWN) + 1; int count3 = ChessCount(board, row, col, LEFT_UP) + ChessCount(board, row, col, RIGHT_DOWN) + 1; int count4 = ChessCount(board, row, col, LEFT_DOWN) + ChessCount(board, row, col, RIGHT_UP) + 1; //判断五子连珠 if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) //有五子连珠,则一定有人赢 //x, y保存的是玩家最近一次落子 if (board[x - 1][y - 1] == PLAYER1) return PLAYER1_WIN; else return PLAYER2_WIN; //这个if-else语句可换成 return board[x-1][y-1]; int i = 0; for (; i < row; i++) int j = 0; for (; j < col; j++) if (board[i][j] == 0) return NEXT; return DRAW; void ShowBoard(int board[][COL], int row, int col) //C语言清屏,减少每次棋盘打印,实现原地刷新效果 printf("\\e[1;1H\\e[2J"); //Linux环境下,C语言实现清屏 printf("\\n"); //将数组内容,进行可视化 printf(" "); //优化棋盘使其美观 int i = 1; for (; i <= col; i++) printf("%3d", i); printf("\\n"); for (i = 0; i < row; i++) int j = 0; printf("%2d ", i + 1); for (; j < col; j++) if (board[i][j] == 0) printf(" . "); else if (board[i][j] == PLAYER1) printf("● "); else printf("○ "); printf("\\n"); void PlayerMove(int board[][COL], int row, int col, int who) //判断玩家的落子位置:合法性、去重 while (1) printf("玩家[%d] 请输入你的落子坐标: ", who); scanf("%d %d", &x, &y); //判断输入坐标的合法性,行列 if (x < 1 || x > row || y < 1 || y > col) printf("位置错误!\\n"); continue; //在数组当当中的下标值 else if (board[x - 1][y - 1] != 0) printf("此位置已被占用!\\n"); continue; else //合法性,去重 board[x - 1][y - 1] = who; break; void Game() int board[ROW][COL]; //在函数中定义数组,其实是一个随机数,需要清空以确定坐标数 /*1.采用ROW,COL型的二维数组,进行游戏信息的保存 2.全部清空有许多种做法:采用双循环,采用Init函数等 3.注:memset按照字节为单位操作,menset内存设置 4.使用memset清空,默认棋盘数据都是0*/ memset(board, 0, sizeof(board)); int result = NEXT; do ShowBoard(board, ROW, COL); //显示棋盘 PlayerMove(board, ROW, COL, PLAYER1);//玩家1先走,也可以随机选择先走——“先手” result = IsOver(board, ROW, COL); //判断游戏是否结束 if (NEXT != result) break; ShowBoard(board, ROW, COL); PlayerMove(board, ROW, COL, PLAYER2); result = IsOver(board, ROW, COL); if (NEXT != result) break; while (1); //Player1 win, Player2 win, Draw switch (result) case PLAYER1_WIN: printf("恭喜玩家1获胜!\\n"); break; case PLAYER2_WIN: printf("恭喜玩家2获胜!\\n"); break; case DRAW: printf("游戏平局,和气生财!\\n"); break; default: //这种情况不会出现,do nothing! break; //ShowBoard(board, ROW, COL);
(2)main.c
#include "game.h" //游戏菜单 void Menu() printf("############################\\n"); printf("## 1. 开始 0. 退出 ##\\n"); printf("############################\\n"); printf(" ————By 作者:新晓·故知\\n"); printf("请选择:"); int main() int quit = 0; //用来判断游戏是否退出 int select = 0; //使得游戏可以多次进行 while (!quit) Menu(); //游戏菜单 scanf("%d", &select); switch (select) //根据用户选择,执行合适的游戏逻辑代码 case 1: Game(); break; case 0: quit = 1; printf("退出游戏,再见!\\n"); break; default: printf("输入错误,请重新输入!\\n"); break; return 0;
(3)game.h
#pragma once #include <stdio.h> #include <string.h> //增强代码可维护性 #define ROW 10 #define COL 10 #define PLAYER1 1 //玩家1编号,默认棋盘数据是0,玩家1落子,该位置被改成1 #define PLAYER2 2 //玩家2编号,默认棋盘数据是0,玩家2落子,该位置被改成2 #define NEXT 0 //游戏继续 #define PLAYER1_WIN 1 #define PLAYER2_WIN 2 #define DRAW 3 //使用枚举,代表方向 enum Dir LEFT, RIGHT, UP, DOWN, LEFT_UP, LEFT_DOWN, RIGHT_UP, RIGHT_DOWN ; void Menu(); //菜单功能声明 void Game(); //游戏功能声明
(4)Makefile
game:game.c main.c ProcBar.c gcc $^ -o $@ .PHONY:clean clean: rm -f game
五、程序调试:
1.程序界面及说明:
(1)进入游戏主程序
(2)默认玩家1为先手
(3)输入玩家坐标
2.测试用例:
(1)输入错误坐标测试:
(2)输入已被占用坐标测试
(3)实现“五子连珠”判断:
六、程序功能扩展:
1.扩展思路:
1.引入进度条
2.尝试人机对战 3.功能扩展:颜色提示,步数记录,先手随机交换等 4.网络版本 5. 将走过的步骤保存在文件里,实现自动下棋,以及扩展至数据库6.nucurses实现鼠标点击
等等
2.扩展实现:
引入进度条:
(1)更改代码:
Makefile:
game:game.c main.c ProcBar.c gcc $^ -o $@ .PHONY : clean clean : rm - f game
main.c:
#include "game.h" #include "ProcBar.h" //游戏菜单 void Menu() printf("############################\\n"); printf("## 1. 开始 0. 退出 ##\\n"); printf("############################\\n"); printf("请选择:");
(2)扩展效果演示:
七、项目总结:
1.核心逻辑:
1.基于二维数组保存数据信息
2.将二维数组可视化
3.每次落子存入数据都需要进行更新可视化
4.落子和判断是强相关的,换句话说,玩家1落子的时候说明上一步玩家二没有赢,每个玩家落子,立即判断输赢
2.项目体现思想:
从五子棋项目中体现出对大型项目先进行顶层逻辑设计,再将任务模块化,最后联动组合封装优化。
八、项目改编:
将Linux环境下的C语言项目改编在Windows环境下,实现运行!借助C语言的跨平台性,进行跨平台改动。
后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!
——By 作者:新晓·故知
井字棋(人机对战版)(代码片段)
...文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似。然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线(包括行、列、对角线、反对角线),则为获胜... 查看详情
双人五子棋对战(需要easyx图像库)
...运行一下玩玩~(虽然==没LOL好玩2333333)设计题目:双人五子棋对战单机游戏使用C语言及VC绘图库,在VC环境下,设计一个双人五子棋对战单机游戏,双方各执黑白一子,黑白双方轮流落子,直到某一 查看详情
结对-结对编项目作业名称-设计文档
设计项目:五子棋游戏设计人员:孙政凯游戏设计平台:pygame安装下载python,pygame复习巩固知识点,设计窗口,设计落子,设计游戏规则,设计关闭窗口按键,检查程序。游戏窗口:480,480游戏模式:人机模式,人人对战游戏双... 查看详情
java课程设计——五子棋
一、团队名称、成员介绍团队名称:啦啦啦队团队成员:?何炎玲【组长】:201821123007网络1811负责模块:人机对战、难度等级、界面设计、撰写团队博客?林莹:201821123034网络1812负责模块:人人对战、胜负判定、计时器、代码规... 查看详情
c语言开发《扫雷》游戏,你从未体验过的联网对战版
...书籍,推荐朱晨冰老师的《VisualC++2017网络编程实战》,出版日期2020年。个人感觉这本书讲解比较细致,内容也不会太老旧,有计网基础会更容易理解学习。程序采用阻塞套接字编写,因此服务器免不了... 查看详情
c语言开发《扫雷》游戏,你从未体验过的联网对战版
一、简介单机版扫雷总会有些枯燥,不妨试试联网对战版扫雷!开发环境:VS2019+EasyX_20210224。游戏玩法:左键按下翻开方块,翻开雷判输,或翻开最后一个方块判赢;逃跑或超时会结束本轮连接... 查看详情
项目——网络对战五子棋(web-gobang)(代码片段)
...景小时候,闲来无事最喜欢和别人玩的游戏之一就是五子棋了,它规则简单,但却玩法多变,直到现在我还时不时的在手机上和别人在线对战。最近自己学习Linux方面的相关知识,学习了多线程和Socket编程... 查看详情
结对-结对编项目作业名称-需求分析
目标要求本次结对编程设计网络休闲益智类游戏——五子棋。这个软件应该达到以下目标:制定合法规则,能够判断出非法操作,以便公正地进行并分出胜负;支持人人对战方便操作和使用。基本规则1、双人对战,由五子棋的... 查看详情
结对-结对编项目作业名称-需求分析
【目标要求】本次结对编程设计网络休闲益智类游戏——五子棋。这个软件应该达到以下目标:制定合法规则,能够判断出非法操作,以便公正地进行并分出胜负;支持人人对战方便用户的操作和使用。【基本规则】1、双人对... 查看详情
结对编程项目五子棋-需求分析
简单介绍五子棋游戏的制作过程与需求支持多个平台的游戏运行,有无网络都可运行玩乐的休闲益智游戏制作:初步设置一个游戏窗口,调节窗口大小画出游戏需要的画面,绘画出需要的落子设置鼠标按键,退出游戏的按键设置... 查看详情
项目——网络对战五子棋(web-gobang)(代码片段)
目录1.项目开发背景2.项目需求&开发环境3.项目设计&项目难点4.功能实现&难点解决4.1.用户登录/注册4.2.项目难点解决4.2.1难点一:当用户点击开始匹配按钮时,创建房间并为用户分配相应的对手。4.2.2难点二:... 查看详情
项目——网络对战五子棋(web-gobang)(代码片段)
目录1.项目开发背景2.项目需求&开发环境3.项目设计&项目难点4.功能实现&难点解决4.1.用户登录/注册4.2.项目难点解决4.2.1难点一:当用户点击开始匹配按钮时,创建房间并为用户分配相应的对手。4.2.2难点二:... 查看详情
qtvs2017《五子棋》人机对战项目(代码片段)
...年了。一年前,自己学习qt语言时,顺便写了一个五子棋的小项目,个人感觉,这个五子棋项目还算挺大型的,整个项目代码量加起来可能有1w行,现在分享出来给有需要的朋友,参考借鉴。项目包括实... 查看详情
简单程序设计-五子棋
《程序设计-五子棋》 作者:蜡笔小黑(原创博文,转载请说明)前言:很多刚刚接触编程的人都不知道怎么下手编写程序,特别是学习了新的知识点... 查看详情
五子棋项目的实现人机对战类的具体设计
在之前描述了博弈树算法的思想,现在则是关键类的设计实现。在具体的过程中我们先要设计一个遍历棋型算法,来遍历整个棋盘中的各种棋型 通过最后返回值的不同,来确定不同的棋型当中有评估函数对当前的棋型进行打... 查看详情
双人组队作业:五子棋
双人组成员:李志刚,刘海威五子棋作为一款棋类竞技运动在民间十分流行,许多人喜欢玩五子棋,为了熟悉五子棋的规则技巧以及简单的人工智能,决定用JAVA开发五子棋游戏。游戏分为人机对战和人人对战。首先设计一个15╳... 查看详情
结对编程作业需求分析—五子棋
五子棋需求分析1.需求分析:五子棋的人机对战复杂,本小组只设计人人对战游戏。具体需求如下:(1)初始化:屏幕初始化,棋盘由纵横各15条等距离、垂直交叉的平行线构成,形成225个交叉点,以对局开始时的黑方为准(2)... 查看详情
c#五子棋小游戏源码(人机对战)
点击查看:C#五子棋小游戏源码(人机对战)文件大小:1.3M操作系统:Windows10旗舰版开发工具:VS2019开发语言:.cs 查看详情