简单程序设计-五子棋

          《程序设计-五子棋》

                        作者:蜡笔小黑(原创博文,转载请说明)

前言:很多刚刚接触编程的人都不知道怎么下手编写程序,特别是学习了新的知识点,不知道有什么用,那么本文将以简单的存储结构及简单的运算,条件语句,分支语句,循环语句结合,带来一个双人对战版五子棋,这是一个简单的模型,实现了五子棋最最基本的功能,还有好多地方需要补全,如边界问题,设计问题,游戏逻辑问题,希望读者阅读后能够注意,通过自己的努力来完善它,还能扩展各种功能,如悔棋,网络对战等,有时候写程序和小生命一样,慢慢会成长,而我们作为“父母”的看到自己的小宝宝成为有用之才,过程之欣喜特别棒!下面正题!

需求分析:通过C++语言来实现一个以windows控制台为展示平台的简单版五子棋程序,其中通过键盘输入来控制游戏中的行为(光标移动、落子、确认)。规则要求某一方在横竖斜方向连续存在五个或五个以上本人所执棋子获得为获胜。

流程设计:

游戏流程分析:

当我们要扒一个已存在的程序时(有的是五子棋的程序,可以在互联网里找到很多),我们可以从他的UI入手,通过我们所观察到的,所感受到,所使用到的服务,来对软件进行分析,从而获得以上流程,但我们一旦需要将需求变为代码时,我们的设计就要考虑的更多了。

这样我们就需要一种能力--抽象

 1.首先,我们需要一个棋盘,那么我可以使用C++里的什么来存储和表示棋盘呢?通过抽象,因为棋盘是个二维图形,我推荐使用二维数组,假设我们构建一个19行*19列的棋盘。

实现:
       int qiPan[19][19];            //声明一个19行19列的数组来存储棋盘 

    for(int h=0;h<19;h++)        //对数组进行遍历,所有元素进行初始化(赋值),默认为0值
    {
        for(int l=0;l<19;l++)
        {
            qiPan[h][l]=0;        //对当前元素进行初始化(赋值),默认为0值
        }
    }

for(int h=0;h<19;h++)        //打印
{
    for(int l=0;l<19;l++)
    {
        switch(qiPan[h][l])
        {
            case 0:         //如果棋盘存储的元素为0时,我们打印 · 样式的字符
                cout<<"·";
                break;
        }
    }
    cout<<endl;
}
运行以上代码,我们可以得到一个棋盘。

2.那么拥有棋盘后,我们需要拥有一个光标,来对落子位置进行定点,那么我如何进行表示呢。我们可以在棋盘上找一个点,也就是在数组对应位置找一个元素,更改他的值,我们用8来表示光标,而找到这个元素我们需要知道其横纵坐标值,我们用两个int变量表示。
    int X=9;                    //2.声明并初始化光标的横纵坐标
    int Y=9;                    

    qiPan[9][9]=8;                //更改棋盘中光标所在元素的值为8

打印时,我们只要在switch 语句中添加一个case 选项 8即可:

case 8:           //如果棋盘存储的元素为0时,我们打印 · 样式的字符
    cout<<"╋";
    break;
获得光标后我们如何移动他呢?那么我们可以通过接受键盘输入的字符来控制光标的移动,本例中使用 W上,S下,A左,D右 来移动光标。
        char xx=getch();            //控制台从键盘获得一个字符的函数(方法)
        switch(xx)                    //控制
        {
            case ‘w‘:                //上
                Y=Y-1;                //使光标纵坐标-1
                qiPan[Y][X]=8;        //将光标写入棋盘
                qiPan[Y+1][X]=0;        //使原本位置的值还原
                break;
            case ‘s‘:                //下
                Y=Y+1;
                qiPan[Y][X]=8;
                qiPan[Y-1][X]=0;
                break;    

            case ‘a‘:                //左
                X=X-1;
                qiPan[Y][X]=8;
                qiPan[Y][X+1]=0;
                break;
            case ‘d‘:                //右
                X=X+1;
                qiPan[Y][X]=8;
                qiPan[Y][X-1]=0;
                break;
        }

3.这时,我们可以控制光标的移动了,接下来要实现落子操作,棋子又怎么表示呢?

我们可以使用两个int类型的值来表示:白子- 1,黑子- 2,那么我们只要在棋盘中更改光标所在位置元素的值为1或2就可以了,那么我们这么做可行吗?

我们回顾一下光标移动的代码,我们会发现,光标的移动会影响元素的变化,那么我们如果在棋盘中进行落子后,我们光标再次移动有可能会改变已记录的落子信息,为了使光标与棋子不冲突,我们使用两个图层,表示两个相同的棋盘。

那么我就需要再声明一个棋盘,方法和1中一样:

    int qiPanTwo[19][19];        //声明一个19行19列的数组来存储棋盘 

    for(int h=0;h<19;h++)        //对数组进行遍历,所有元素进行初始化(赋值),默认为0值
    {
        for(int l=0;l<19;l++)
        {
            qiPanTwo[h][l]=0;    //对当前元素进行初始化(赋值),默认为0值
        }
    }

好,棋盘2已经建立好了,那么我们如何落子?我们一定要选择执棋方后,在光标位置通过接收键盘输入的j落子,那么我们只需要在2.中switch语句中添加一个分支 case ’j’:即可,并且我们需要使用一个变量来表示玩家,我们可以在程序一开始定义:

int player=1;//设定玩家并进行初始化赋值

case ‘j‘:                    //落子
    if(player==1)            //如果当前玩家为白色方时
    {
        qiPanTwo[Y][X]=1;    //通过棋盘1中的光标位置更改棋盘2
//中对应元素的值为1,也就是白棋落子
        player=2;            //白棋落子后更换玩家
    }
    else if(player==2)
    {
        qiPanTwo[Y][X]=2;
        player=1;
    }
break;
落子成功,接下来我们可以把它展示出来,由于此时我们要对两个棋盘进行统一的打印,那么我们使用swicth就不能进行统一的分支选择了,此时我们需要将1.中的打印内容改为:
        if(qiPan[h][l]==8)   //由于光标所在图层应该在棋子图层之上,所以优先考虑。
        {
            cout<<"╋";
        }
        else if(qiPanTwo[h][l]==0)
        {
            cout<<"·";
        }
        else if(qiPanTwo[h][l]==1)
        {
            cout<<"●";
        }
        else if(qiPanTwo[h][l]==2)
        {
            cout<<"○";
        }
4.游戏规则,我们落子之后要进行一个判断,如何判断是否胜利呢?
      此时,我们就要使用游戏规则来进行算法的分析,当落子位横、纵、斜5格内存在相互连接的五个同类棋子时,我们可认为执该棋者获胜,所以我们需要在各个方向进行判断。
        int shu=1,heng=1,pie=1,na=1;//横竖撇捺计数器,累计到5则表示某方向出现五个相同的旗子
        for(int i=1;i<=4;i++) //上
        {
            if(qiPanTwo[Y+i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              shu++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //下
        {
            if(qiPanTwo[Y-i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              shu++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左
        {
            if(qiPanTwo[Y][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              heng++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右
        {
            if(qiPanTwo[Y][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              heng++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左下
        {
            if(qiPanTwo[Y+i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              pie++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右上
        {
            if(qiPanTwo[Y-i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              pie++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右下
        {
            if(qiPanTwo[Y+i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              na++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左上
        {
            if(qiPanTwo[Y-i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              na++;
            else
              break;
        }
        if(shu==5||heng==5||pie==5||na==5)
        {
            if(qiPanTwo[Y][X]==1)
                {
                    cout<<"白子获胜!";
                    system("pause");
                    break;
                }
            else
                {
                    cout<<"黑子获胜!";
                    system("pause");
                    break;
                }
        }
        shu=1,heng=1,pie=1,na=1;    

好 当完成这一步时,我们的程序基本就搞定了,剩下就是按照一开始的流程进行拼接了,其中我们在打印屏幕之前,要对上一次打印的结果进行擦除,使用函数
system(“cls”);//擦除控制台中所有已显示的字符
就可以完成了。

完整代码(可运行):

#include<iostream>
#include<string>
#include<windows.h>
#include<conio.h>
using namespace std;
int main()
{
    int player=1;                //定义一个玩家,当1时为白方,2时为黑方 

    //................................棋盘1..............................................

    int qiPan[19][19];            //1.声明一个19行19列的数组来存储棋盘 1 

    for(int h=0;h<19;h++)        //对数组进行遍历,所有元素进行初始化(赋值),默认为0值
    {
        for(int l=0;l<19;l++)
        {
            qiPan[h][l]=0;        //对当前元素进行初始化(赋值),默认为0值
        }
    }

    //...............................棋盘2................................................

    int qiPanTwo[19][19];        //声明一个19行19列的数组来存储棋盘  2

    for(int h=0;h<19;h++)        //对数组进行遍历,所有元素进行初始化(赋值),默认为0值
    {
        for(int l=0;l<19;l++)
        {
            qiPanTwo[h][l]=0;    //对当前元素进行初始化(赋值),默认为0值
        }
    }

    //...............................光标声明.............................................

    int X=9;                    //2.声明并初始化光标的横纵坐标
    int Y=9;
    qiPan[9][9]=8;

    //..............................显示...................................................

    for(int h=0;h<19;h++)
        {
            for(int l=0;l<19;l++)
            {

                if(qiPan[h][l]==8)
                {
                    cout<<"╋";
                }
                else if(qiPanTwo[h][l]==0)
                {
                    cout<<"·";
                }
                else if(qiPanTwo[h][l]==1)
                {
                    cout<<"●";
                }
                else if(qiPanTwo[h][l]==2)
                {
                    cout<<"○";
                }
            }
            cout<<endl;
        }

    //..............................输入控制...............................................

    while(true)
    {
        char xx=getch();            //控制台从键盘获得一个字符
        switch(xx)                    //控制
        {
            case ‘w‘:                //上
                Y=Y-1;                //使光标纵坐标-1
                qiPan[Y][X]=8;        //讲光标写入棋盘
                qiPan[Y+1][X]=0;        //使原本位置的值还原
                break;

            case ‘s‘:                //下
                Y=Y+1;
                qiPan[Y][X]=8;
                qiPan[Y-1][X]=0;
                break;    

            case ‘a‘:                //左
                X=X-1;
                qiPan[Y][X]=8;
                qiPan[Y][X+1]=0;
                break;

            case ‘d‘:                //右
                X=X+1;
                qiPan[Y][X]=8;
                qiPan[Y][X-1]=0;
                break;    

            case ‘j‘:                    //落子
                if(player==1)            //如果当前玩家为白色方时
                {
                    qiPanTwo[Y][X]=1;    //通过棋盘1中的光标位置更改棋盘2中对应元素的值为1,也就是白棋落子
                    player=2;            //白棋落子后更换玩家
                }
                else if(player==2)
                {
                    qiPanTwo[Y][X]=2;
                    player=1;
                }
                break;
        }

    //................................清屏操作................................................    

        system("cls");                

    //...............................打印.....................................................

        for(int h=0;h<19;h++)
        {
            for(int l=0;l<19;l++)
            {

                if(qiPan[h][l]==8)
                {
                    cout<<"╋";
                }
                else if(qiPanTwo[h][l]==0)
                {
                    cout<<"·";
                }
                else if(qiPanTwo[h][l]==1)
                {
                    cout<<"●";
                }
                else if(qiPanTwo[h][l]==2)
                {
                    cout<<"○";
                }
            }
            cout<<endl;
        }

    //.........................游戏规则..............................................

        int shu=1,heng=1,pie=1,na=1;//横竖撇捺
        for(int i=1;i<=4;i++) //上
        {
            if(qiPanTwo[Y+i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              shu++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //下
        {
            if(qiPanTwo[Y-i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              shu++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左
        {
            if(qiPanTwo[Y][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              heng++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右
        {
            if(qiPanTwo[Y][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              heng++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左下
        {
            if(qiPanTwo[Y+i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              pie++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右上
        {
            if(qiPanTwo[Y-i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              pie++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //右下
        {
            if(qiPanTwo[Y+i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              na++;
            else
              break;
        }
        for(int i=1;i<=4;i++) //左上
        {
            if(qiPanTwo[Y-i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0)
              na++;
            else
              break;
        }
        if(shu==5||heng==5||pie==5||na==5)
        {
            if(qiPanTwo[Y][X]==1)
                {
                    cout<<"白子获胜!";
                    system("pause");
                    break;
                }
            else
                {
                    cout<<"黑子获胜!";
                    system("pause");
                    break;
                }
        }
    } 

    return 0;
}
     

2017-02-01    20:13:59

时间: 2024-08-07 08:36:21

简单程序设计-五子棋的相关文章

[0318]C++简单程序设计-2

南京信息工程大学实验报告 实验名称 C++简单程序设计-2 实验日期 2018-3-20 得分 指导教师 耿学华 系 计软院 专业 计嵌+软嵌 年级 2017 级 班次 (1) 姓名 施昊阳 学号 20161334026 [toc] 一.实验目的 理解和掌握 C++中函数的定义与使用方法 理解 C++中函数调用过程中值传递与引用传递的区别 灵活.综合运用 C++中分支结构.循环结构及 continue.break 等应用编程求解问题. 二.实验准备 实验前,请围绕以下内容预习/复习指定内容 C+

使用pygame实现一个简单的五子棋游戏

前言写程序已经丢掉很长一段时间了,最近觉得完全把技术丢掉可能是个死路,还是应该捡起来,所以打算借CSDN来记录学习过程, 由于以前没事的时候断断续续学习过python和用flask框架写过点web,所以第一步想捡起python,但是,单纯学习python有点枯燥,正好看到pygame,感觉还挺简单,所以想先写个小游戏练练手. 准备python基础相关准备: pygame的基础知识,参考目光博客的“用Python和Pygame写游戏-从入门到精通” 安装python 3.8.0 在python官网

简单AI五子棋,js,canvas

新年第一篇博客,最近几天走亲访友的没有学习.今天开始进入学习模式. <!DOCTYPE html> <html> <head> <title>五子棋</title> <link rel="stylesheet" type="text/css" href="./css/style.css"> </head> <body> <canvas id=&q

C++——简单程序设计

1.一个简单的程序 #include <iostream> //iostream是头文件,用来说明要使用的对象的相关信息. using namespace std; //使用命名空间,解决类重名的问题,不同的名字空间中的同名类不会引起程序错误. int main() //主函数--执行一定的功能的模块,是程序执行的入口.一个C++程序有且只有一个主函数. { cout<<"Hello!\n"; //cout是输出流类的对象. cout<<"

实验1:c++简单程序设计(1)

//文中有格式错误请无视 //这个编辑器一言难尽 实验目的 1. 掌握c++中类c部分的编程知识: 数据类型,常量,变量,运算符,表达式,分支结构,循环结构 2. 掌握C++中数据输入和输出的基本方法 3. 熟练使用c++程序开发环境,掌握c++程序编写.编译.运行.调试的方法 实验准备 1. 简单的c++程序结构 学习/复习教材「2.1.3 C++程序实例」 2. c++中数据输入输出的基本方法 学习/复习教材2.3节,学习C++中I/O流.预定义的插入符<<和提取符>>的基本用

sql server 简单程序设计1

@  局部变量 @@  全局变量 1.求10的阶层 2.case then ..... . . end 的应用

sql server 简单程序设计2

1.case then ..... . . end 的应用

第二章:C++简单程序设计

主要内容: 1.C++语言概述 2.基本数据类型和表达式 3.数据的输入与输出 4.算法的基本控制结构 5.自定义数据类型 1.数据类型default is double 2.自定义数据类型就是built-in以外的非基本数据类型.

C++简单程序设计-1

四.实验结论 编程练习(1) 源代码: /*输入 1~7 的整数,如果输入的是 1~5,则输出"workday. Let's work hard":如果输入的是 6~7,则输出"weekend. Let's have a rest." */ #include<iostream> using namespace std; int main() { int day; cin>>day; if(day>=1&&day<=