Linux项目实战——五子棋(单机人人对战版)

这篇具有很好参考价值的文章主要介绍了Linux项目实战——五子棋(单机人人对战版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux操作系统项目实战——五子棋

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

GIF:

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

目录

           Linux操作系统项目——五子棋

一、问题导引:

二、实现要求:

三、五子棋原理:

1.落子数据信息保存载体:

2.落子思路:

3.判断“五子连珠”

四、项目实现步骤:

Ⅰ.创建目录及文件:

1.在Linux环境下创建名为Gobang的文件目录:

Ⅱ、输入Linux环境指令进入目录及文件:

Ⅲ、Linux环境编程实现:

1.顶层逻辑设计:

2.模块化设计:

3.联动模块组合封装:

        完整代码:

(1)game.c

(2)main.c

(3)game.h

(4)Makefile

 五、程序调试:

1.程序界面及说明:

2.测试用例:

六、程序功能扩展:

1.扩展思路:

2.扩展实现:

引入进度条:​

(1)更改代码:

(2)扩展效果演示:​

七、项目总结:

1.核心逻辑:

2.项目体现思想:

八、项目改编:

后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!                                                       ——By 作者:新晓·故知


一、问题导引:

在进行Linux入门学习后,通过运用Linux环境指令操作、Vim编辑器、学习五子棋的基本原理等,进行Linux环境下的简单的五子棋项目实现。

生活中的五子棋:

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互   linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

从上图可以看出,五子棋(这类棋)有先手、后手之分(当然也有禁手、俗手、妙手等),这里只进行简单的交互式、窗口化项目实现。(上图涉及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五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

Ⅲ、Linux环境编程实现:

1.顶层逻辑设计:

输入Linux指令:linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(1)

vim Makefile

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(2)

vim game.h

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

 (3)

vim game.c

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(4)

vim main.c

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

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)进入游戏主程序linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互 

(2)默认玩家1为先手

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

 (3)输入玩家坐标

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

2.测试用例:

(1)输入错误坐标测试:

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(2)输入已被占用坐标测试

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(3)实现“五子连珠”判断:

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

六、程序功能扩展:

1.扩展思路:

1.引入进度条

2.尝试人机对战
3.功能扩展:颜色提示,步数记录,先手随机交换等
4.网络版本
5. 将走过的步骤保存在文件里,实现自动下棋,以及扩展至数据库

6.nucurses实现鼠标点击

等等

2.扩展实现:

引入进度条:linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

(1)更改代码:

这里我们需要像之前那样创建ProcBar的文件,这里就直接在Gobang目录下创建ProcBar项目:

touch ProcBar.h
touch ProcBar.c

编辑ProcBar内容:

vim ProcBar.h
vim ProcBar.c

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互 这个内容见博客链接:(在这篇博客的最后一项:Linux第一个小程序——ProcBar(进度条))<Linux常用开发工具使用(yum、vim、gcc/g++、gdb、make/Makefile等)>——《Linux》_新晓·故知的博客-CSDN博客

 

在Gobang的主程序里main.c 加入ProcBar的调用:

vim main.c

把process_bar();添加到 main.c。

linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

#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;

    process_bar();

    //使得游戏可以多次进行
    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;
}

然后修改其他地方,进行联合编译:

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)扩展效果演示:linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互

七、项目总结:

1.核心逻辑:

1.基于二维数组保存数据信息

2.将二维数组可视化

3.每次落子存入数据都需要进行更新可视化

4.落子和判断是强相关的,换句话说,玩家1落子的时候说明上一步玩家二没有赢,每个玩家落子,立即判断输赢

2.项目体现思想:

从五子棋项目中体现出对大型项目先进行顶层逻辑设计,再将任务模块化,最后联动组合封装优化。

八、项目改编:

将Linux环境下的C语言项目改编在Windows环境下,实现运行!借助C语言的跨平台性,进行跨平台改动。linux五子棋,《Linux》,《项目》,linux,centos,vim,后端,交互文章来源地址https://www.toymoban.com/news/detail-777950.html

后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!
                                                                                    ——By 作者:新晓·故知

到了这里,关于Linux项目实战——五子棋(单机人人对战版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++在线五子棋对战(网页版)项目:websocket协议

    目标:认识理解websocket协议、websocket切换过程和websocket协议格式。认识和学会使用websocketpp库常用接口。了解websocketpp库搭建服务器流程,认识和学会使用websocketpp库bin接口,最后使用websocketpp库搭建服务器。 平时我们在逛某宝,点击商品查看商品信息,从HTTP角度来看,就是客

    2024年02月13日
    浏览(34)
  • C++项目:在线五子棋对战网页版--数据模块开发

    数据管理模块,基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。因此,在数据库中,我需要为每一张表创建出对应类,通过类实例化的对象来访问这张数据库表中的数 据,这样的话当我们要访问哪张表的时候,使⽤哪个类实例化的对象即可。 那么在五子

    2024年02月13日
    浏览(27)
  • 基于FPGA(basys3)的双人对战人机对战五子棋(vivado)课程设计项目

    目录 主界面显示与选择模式 双人对战 人机对战 胜利界面显示 部分源码 VGA显示器显示图片,显示图片利用Block Memory Generator将图片像素点储存在RAM里面。 效果图:(防止侵权打了马赛克)  通过开发板上的按键进行模式选择,模式确定 双人对战就是采用简单的存数组的办法

    2024年01月18日
    浏览(31)
  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

    匹配成功返回数据 1. message消息类别 2. ok 3. reson 4. 房间id 5. 双方id 6.白色玩家 一个类记录房间中的信息(房间id,两个用户id,是否为白棋) 信息提示框 处理匹配API 初始化游戏(棋盘,下一个棋子,接受棋子处理响应,判断是否结束) 1. 客户端连接到游戏房间后, 服务器返回

    2024年02月13日
    浏览(38)
  • 在线五子棋对战

    目录   数据管理模块(数据库设计) 前端界面模块 业务处理模块 会话管理模块网络通信模块(session,cookie) 在线管理模块 房间管理模块 用户匹配模块 项目扩展 数据库中有可能存在很多张表,每张表中管理的数据⼜有不同,要进⾏的数据操作也各不相同,因此我们可以为每⼀

    2024年02月14日
    浏览(35)
  • 2.6.C++项目:网络版五子棋对战之数据管理模块-游戏房间管理模块的设计

    对匹配成功的玩家创建房间,建立起一个小范围的玩家之间的关联关系! 房间里一个玩家产生的动作将会广播给房间里的其他用户。 将这些房间管理起来,以便于进行房间生命周期的控制! 游戏房间类: // 实现两个部分: // 1. 房间的设计 // 2. 房间管理的设置 // 游戏房间的

    2024年02月08日
    浏览(33)
  • 在线五子棋对战 --- 人机对战的实现

    要增添一个人机对战的模块, 最大的难点就是如何让人机知道下在什么位置是最好的, 不仅要具备进攻的能力, 还需要具备防守的能力. 这里当人机第一次走的时候, 采用标准开局, 下子在最中间. 当玩家走了之后, 人机就需要去判定下在什么位置合理. 这里采用的是评分表的方法

    2024年02月05日
    浏览(31)
  • C++ 实现对战AI五子棋

     个人主页: 日刷百题 系列专栏 : 〖C/C++小游戏〗 〖Linux〗 〖数据结构〗   〖 C语言 〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​      为了能够快速上手一门语言,我们往往在学习了基本语法后,采用写一个小项目的方式来加深理解语言的语法及运用,本文采

    2024年02月03日
    浏览(44)
  • 基于Python的五子棋人机对战

    在之前的博文基于tkinter的五子棋游戏中使用tkinter做了一个简单的五子棋游戏,只能实现人人对战,后来想着加上人机对战的功能。 不过,最初想想还是挺麻烦的,计算机怎么评估当前的棋局,找到最佳或者较佳的落子点呢,脑子真是越来越不灵光了。站在巨人的肩膀上,科

    2024年02月04日
    浏览(30)
  • JAVA五子棋手机网络对战游戏的设计与实现(源代码+论文)

    在现代社会中,手机及其它无线设备越来越多的走进普通老百姓的工作和生活。 随着3G技术的普及与应用,基于Java开发的软件在手机上的使用非常的广泛,手机增值服务的内容也是越来越多,对丰富人们的生活内容、提供快捷的资讯起着不可忽视的作用。 本文基于J2ME技术,以

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包