linux下C实现打转块小游戏(二)

/*
fun.c源文件
*/
#include <curses.h>
#include <signal.h>
#include <sys/time.h>
#include "play.h"
#include <stdio.h>
#include <stdlib.h>

void init(void);
void exit_a(void);
void paint_boat(int);
void paint_table(int, int, int);
int settimer(int);
void move_person(int);
void win(void);
void lost(void);
struct person p1;
int beg_boat;
void main(void)
{
    long ch;

    init();
    signal(SIGINT, SIG_IGN);
    /*
    设置定时器,单位出发时间初始化为20毫秒。
    小球水平,垂直方向运动,以单位定时器的倍数为准,加入为x:5,则触发五次定时器,则小球横向移动一个单元格,
    加速,是通过减少相应方向定时器的倍数。
    */
    signal(SIGALRM, move_person );
    settimer(20);
    while ((ch = getch()) != ‘q‘){
        if (ch == KEY_LEFT)
            paint_boat(1);
        if (ch == KEY_RIGHT)
            paint_boat(-1);
        if (ch == ‘ ‘)
            signal(SIGALRM, SIG_IGN);
        if (ch == ‘c‘) {
            signal(SIGALRM, move_person);
            settimer(20);
        }
        if (ch == ‘w‘) {
            if (p1.y_ttm > SPEED_MIN)
                p1.y_ttm--;    
        }
        if (ch == ‘s‘) {
            if (p1.y_ttm < SPEED_MAX)
                p1.y_ttm++;
        }
        if (ch == ‘a‘) {
            if (p1.x_ttm > SPEED_MIN)
                p1.x_ttm--;
        }
        if (ch == ‘d‘) {
            if (p1.x_ttm < SPEED_MAX)
                p1.x_ttm++;
        }
    }
}
/*
    退出时调用,用于恢复终端属性
*/
void exit_a(void)
{
    endwin();
}
/*
    初始化
*/
void init(void)
{
    int n, m; 
    //初始化小球基本信息
    p1.remain = (MINE_BOT - MINE_TOP + 1)*(MINE_RIGHT - MINE_LEFT + 1);
    p1.score = 0;
    //init the person
    p1.pos_x = (LEFT_COL + RIGHT_COL)/2;
    p1.pos_y = BOT_LINE;
    p1.dir_x = LEFT;
    p1.dir_y = UP;
    p1.x_ttm = p1.x_ttg = 4;
    p1.y_ttm = p1.y_ttg = 4;
    p1.per = CHAR_PERSON;
    //设置终端属性,函数来自与curses库
    atexit(exit_a);
    initscr();
    noecho();
    keypad(stdscr, TRUE);
    crmode();
    //paint the edge 
    for (n = TOP_LINE - 1; n <= (BOT_LINE + 1); n++) {
        mvaddch(n, LEFT_COL - 1, CHAR_EDGE);
        mvaddch(n, RIGHT_COL + 1, CHAR_EDGE);
        mvaddch(n, LEFT_COL - 2, CHAR_EDGE);
        mvaddch(n, RIGHT_COL + 2, CHAR_EDGE);
    }
    
    for (n = LEFT_COL - 1; n <= (RIGHT_COL + 1); n++) {
        mvaddch(TOP_LINE - 1, n, CHAR_EDGE);
        mvaddch(TOP_LINE - 2, n, CHAR_EDGE);
    }
    //paint table
    paint_table( RIGHT_COL + 5, TOP_LINE + 5, 0);
    //paint mine
    for(n = MINE_TOP ; n <= MINE_BOT; n++)
        for (m = MINE_LEFT; m <= MINE_RIGHT; m++)
            mvaddch(n, m, CHAR_MINE);    
    
    // paint boat
    beg_boat = (LEFT_COL + RIGHT_COL)/2 - LENGTH_BOAT/2;
    paint_boat(1);
    //paint the person
    mvaddch(p1.pos_y, p1.pos_x, p1.per);
    refresh();
}
//打印信息表,分数等,x,y为打印位置,how:0擦除,1打印
void paint_table(int x, int y, int how)
{
    
    char tot[15];
    char rem[15];
    char sco[15];
    char spe_x[15];
    char spe_y[15];
    //char s_p_x[15];    
    //char s_p_y[15];
    //char s_d_x[15];
    //char s_d_y[15];
    static int flag  = 0;
    if (how == 0) {
        mvaddstr(y,     x, "            ");
        mvaddstr(y + 1, x, "            ");
        mvaddstr(y + 2, x, "            ");
        mvaddstr(y + 3, x, "            ");
        mvaddstr(y + 4, x, "            ");
        //mvaddstr(y + 5, x, "            ");
        //mvaddstr(y + 6, x, "            ");
        //mvaddstr(y + 7, x, "            ");
        
    } else {
        sprintf(tot, "TOTAL: %d", (MINE_BOT - MINE_TOP + 1)*(MINE_RIGHT - MINE_LEFT + 1));
        sprintf(rem, "REMAIN:%d", p1.remain);
        sprintf(spe_x, "SPEED_X: %d", SPEED_MAX - p1.x_ttm);
        sprintf(spe_y, "SPEED_Y: %d", SPEED_MAX - p1.y_ttm);
        sprintf(sco, "SCORE: %d", p1.score);
        //sprintf(s_p_x, "P_X: %d", p1.pos_x);
        //sprintf(s_p_y, "P_Y: %d", p1.pos_y);
        //sprintf(s_d_x, "D_X: %d", p1.dir_x);
        //sprintf(s_d_y, "D_Y: %d", p1.dir_y);
        mvaddstr(y,     x, tot);
        mvaddstr(y + 1, x, rem);
        mvaddstr(y + 2, x, spe_x);
        mvaddstr(y + 3, x, spe_y);
        mvaddstr(y + 4, x, sco);
        //mvaddstr(y + 4, x, s_p_x);
        //mvaddstr(y + 5, x, s_p_y);
        //mvaddstr(y + 6, x, s_d_x);
        //mvaddstr(y + 7, x, s_d_y);
    }
}
//打印短板,dir表示方向,1向左,-1向右
void paint_boat(int dir)
{
    int n;

    for ( n = 0; n < LENGTH_BOAT; n++)
        mvaddch(BOT_LINE + 1, n + beg_boat, BLANK );
    if (dir == 1 && beg_boat > LEFT_COL) 
        beg_boat--;
    if (dir == -1 && beg_boat < (RIGHT_COL +1- LENGTH_BOAT))
        beg_boat++;
    for ( n = 0; n < LENGTH_BOAT; n++)
        mvaddch(BOT_LINE + 1, n + beg_boat, CHAR_BOAT );
    refresh();

}
//设置定时器
int settimer(int msec)
{
    struct itimerval new;
    long n_sec, n_usec;
    
    n_sec = msec/1000;
    n_usec = (msec%1000)*1000L;
    new.it_interval.tv_sec = n_sec;//下次触发时间
    new.it_interval.tv_usec = n_usec;    
    new.it_value.tv_sec = n_sec;//定时器间隔时间
    new.it_value.tv_usec = n_usec;
    return setitimer(ITIMER_REAL, &new, NULL);
}
/*
    查看小球是否触碰到砖块
    大砖块,分为两类,一类小球贴在砖块上,一类小球打在砖块上,不同方式对小球的运动影响不同
*/
void dig_mine(void)
{
    int n_x, n_y;
    static int min_val[MINE_BOT - MINE_TOP + 1][MINE_RIGHT - MINE_LEFT + 1];
    
    n_y = p1.pos_y - MINE_TOP;
    n_x = p1.pos_x - MINE_LEFT;
    //打, 小球位置恰好为砖块位置,根据小球目前运动方向,四周砖块情况,决定怎么改变小球的运动状态(方向),并消除砖块,增加积分等。
    if (n_x >= 0 && n_x <= (MINE_RIGHT - MINE_LEFT) && n_y >= 0 && n_y <= (MINE_BOT - MINE_TOP))
        if (min_val[n_y][n_x] == MINE_HIDE) {
            if (n_y - 1 >=0 && min_val[n_y - 1][n_x] == MINE_HIDE)
                p1.dir_y = -p1.dir_y;
            if (n_y + 1 <= (MINE_BOT - MINE_TOP) && min_val[n_y + 1][n_x] == MINE_HIDE)
                p1.dir_y = -p1.dir_y;
            if (n_x - 1 >= 0 && min_val[n_y][n_x - 1] == MINE_HIDE)
                p1.dir_x = -p1.dir_x;
            if (n_x + 1 <= (MINE_RIGHT - MINE_LEFT) && min_val[n_y][n_x + 1] == MINE_HIDE)
                p1.dir_x = -p1.dir_x;
            min_val[n_y][n_x] = MINE_DIG;
            mvaddch(p1.pos_y, p1.pos_x, BLANK);
            p1.remain--;
            p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10;
            return;
        }
        //贴,小球运动方向上,下一个位置,恰好是砖块位置(重点),根据四周情况,改变小球运动状态
    if (n_x + 1 >= 0 && n_x - 1 <= (MINE_RIGHT - MINE_LEFT) && n_y + 1 >= 0 && n_y - 1<= (MINE_BOT - MINE_TOP)) {
        if (n_y - 1 >=0 && n_x >= 0 && n_x <= MINE_RIGHT - MINE_LEFT)
            if (min_val[n_y - 1][n_x] == MINE_HIDE&& p1.dir_y == UP) {
                min_val[n_y -1 ][n_x] = MINE_DIG;
                mvaddch(p1.pos_y - 1, p1.pos_x, BLANK);
                p1.remain--;
                p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10;
                p1.dir_y = -p1.dir_y;
            }
        if (n_y + 1 <= MINE_BOT - MINE_TOP && n_x >= 0 && n_x <= MINE_RIGHT - MINE_LEFT)
            if (min_val[n_y + 1][n_x] == MINE_HIDE&& p1.dir_y == DOWN) {
                min_val[n_y + 1][n_x] = MINE_DIG;
                mvaddch(p1.pos_y + 1, p1.pos_x, BLANK);
                p1.remain--;
                p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10;
                p1.dir_y = -p1.dir_y;
            }
        if (n_x - 1 >= 0 && n_y >= 0 && n_y <= MINE_BOT - MINE_TOP)
            if (min_val[n_y][n_x - 1] == MINE_HIDE&& p1.dir_x == LEFT) {
                min_val[n_y][n_x - 1] = MINE_DIG;
                mvaddch(p1.pos_y, p1.pos_x - 1, BLANK);
                p1.remain--;
                p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10;
                p1.dir_x = -p1.dir_x;
            }    
        if (n_x + 1 <= MINE_RIGHT - MINE_LEFT && n_y >= 0 && n_y <= MINE_BOT - MINE_TOP)
            if (min_val[n_y][n_x + 1] == MINE_HIDE&& p1.dir_x == RIGHT) {
                min_val[n_y][n_x + 1] = MINE_DIG;
                mvaddch(p1.pos_y, p1.pos_x + 1, BLANK);
                p1.remain--;
                p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10;
                p1.dir_x = -p1.dir_x;
            }
    }
}
/*
    小球运行判定函数
*/
void move_person(int signo)
{
    signal(SIGALRM, SIG_IGN);
    int flag = 0, bef_x, bef_y;
    bef_x = p1.pos_x;
    bef_y = p1.pos_y;
    //指定次数定时器是否触发
    if (p1.x_ttm > 0 && p1.x_ttg-- == 1) {
        p1.x_ttg = p1.x_ttm;
        flag += 2;
    }
    if (p1.y_ttm > 0 && p1.y_ttg-- == 1) {
        p1.y_ttg = p1.y_ttm;
        flag += 1;
    }
    if (flag > 0) {
        //lost 判定小球是否越出下边界,是,则失败,结束
        if (p1.dir_y == DOWN && bef_y == BOT_LINE) 
            if (bef_x < beg_boat || bef_x >= (beg_boat + LENGTH_BOAT)) {
                paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0);
                paint_table(LEFT_COL + 6, TOP_LINE + 4, 1);    
                lost();
                return;
            }
            else
                p1.dir_y = -p1.dir_y;
        //win 判定砖块被全打光,是 ,胜利,游戏结束
        if (p1.remain == 0) {
            paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0);
            paint_table(LEFT_COL + 6, TOP_LINE + 4, 1);    
            win();
            return;
        }
        //小球在砖块潜在位置,才进行砖块判定
        if (p1.pos_x >= MINE_LEFT - 1 && p1.pos_x <= MINE_RIGHT+1 && p1.pos_y >= MINE_TOP - 1 && p1.pos_y <= MINE_BOT+1)
            dig_mine();
        if (flag == 1)
            p1.pos_x += p1.dir_x;
        else if (flag == 2)
            p1.pos_y += p1.dir_y;
        else {
            p1.pos_x += p1.dir_x;
            p1.pos_y += p1.dir_y;    
        }
        //打印信息表
        paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0);
        paint_table(RIGHT_COL + 5, TOP_LINE + 5, 1);
        mvaddch(bef_y, bef_x, BLANK);
        //当小球,遇到上,左,右边界时,改变运行方向
        if ( p1.dir_x == LEFT &&p1.pos_x == LEFT_COL)     
            p1.dir_x = -p1.dir_x;
        if (p1.dir_x == RIGHT && p1.pos_x == RIGHT_COL) 
            p1.dir_x = -p1.dir_x;
        if (p1.dir_y == UP &&p1.pos_y == TOP_LINE)      
            p1.dir_y = -p1.dir_y;
        mvaddch(p1.pos_y, p1.pos_x, CHAR_PERSON);
        move(LINES - 1, COLS -1);
        refresh();
    }
    signal(SIGALRM, move_person);
}
//成功时,打印
void win(void)
{
    move(TOP_LINE + 3, LEFT_COL + 20);
    printw("%s", "                                          ");
    move(TOP_LINE + 4, LEFT_COL + 20);
    printw("%s", "*   *   ***   *   *   *  *  *  *  **   *  ");
    move(TOP_LINE + 5, LEFT_COL + 20);
    printw("%s", " * *   *   *  *   *   *  *  *  *  * *  *  ");
    move(TOP_LINE + 6, LEFT_COL + 20);
    printw("%s", "  *    *   *  *   *   *  *  *  *  *  * *  ");
    move(TOP_LINE + 7, LEFT_COL + 20);
    printw("%s", "  *    *   *  *   *   * * * *  *  *   **  ");
    move(TOP_LINE + 8, LEFT_COL + 20);
    printw("%s", "  *     ***    ***     *   *   *  *    *  ");
    move(TOP_LINE + 9, LEFT_COL + 20);
    printw("%s", "                                          ");
    refresh();
}
//失败时打印
void lost(void)
{

    move(TOP_LINE + 3, LEFT_COL + 20);
    printw("%s", "                                                 ");
    move(TOP_LINE + 4, LEFT_COL + 20);
    printw("%s", "*   *  ***  *   *   *     ***   ****  ***** ");
    move(TOP_LINE + 5, LEFT_COL + 20);
    printw("%s", " * *  *   * *   *   *    *   * *        *   ");
    move(TOP_LINE + 6, LEFT_COL + 20);
    printw("%s", "  *   *   * *   *   *    *   *  ****    *   ");
    move(TOP_LINE + 7, LEFT_COL + 20);
    printw("%s", "  *   *   * *   *   *    *   *      *   *   ");
    move(TOP_LINE + 8, LEFT_COL + 20);
    printw("%s", "  *    ***   ***    ****  ***   ****    *   ");
    move(TOP_LINE + 9, LEFT_COL + 20);
    printw("%s", "                                                 ");
    refresh();
}

算法未经允许,请勿转载,谢谢。

时间: 2024-10-08 13:18:39

linux下C实现打转块小游戏(二)的相关文章

JS实现别踩白块小游戏

最近有朋友找我用JS帮忙仿做一个别踩白块的小游戏程序,但他给的源代码较麻烦,而且没有注释,理解起来很无力,我就以自己的想法自己做了这个小游戏,主要是应用JS对DOM和数组的操作. 程序思路:如图:将游戏区域的CSS设置为相对定位.溢出隐藏;两块“游戏板”上分别排布着24块方格,黑色每行随机产生一个,“游戏板”向下滚动并交替显示,将每个操作板的黑块位置存入数组,每次点击时将数组pop出来进行比对(我觉得亮点在这……). 这里是游戏的GitHub地址,大家可以到里点击中部菜单最右边的的Downloa

js实现2048小游戏二维数组更新算法

2048小游戏是当下比较流行的益智游戏了,而它最关键的模块莫过于当手指滑过或鼠标按下后如何确定更新的值. 首先该游戏可以看作一个4*4的二维数组的更新游戏,玩家通过控制数组内元素的合并来不断产生更大的数字,当方向确定时,每一行或每一列的计算方式实际上是一样的,例如,当我确定方向为向左时,每一行的计算方式都是一样的,这样,我们就可以将二维数组的计算简化为一维数组的计算了,然后通过循环计算其他行即可. 而一维数组中主要就是寻找相邻的两个非空值进行合并,相关函数可表示如下: // 一维数组合并相邻非空

Linux下php+mysql+nginx编译搭建(二)

之前一直都是一键搭建的web服务器,但是一键搭建的环境相对来说都是比较老的.如果要用比较新的环境,特别是正式服务器,就必须自己手动编译搭建了(以下搭建基于linux centos6.5 32位服务器). 二.安装mysql 进入安装目录: Cd /opt 下载并解压: wget http://downloads.mysql.com/archives/mysql-5.0/mysql-5.5.30.tar.gz tar -zxf mysql-5.5.30.tar.gz 编译安装: cmake \ -

Linux 下UVC&amp;amp;V4L2技术简单介绍(二)

通过前文Linux 下UVC&V4L2技术简单介绍(一)我们了解了UVC和V4L2的简单知识. 这里是USB设备的文档描写叙述:http://www.usb.org/developers/docs/devclass_docs/ 那么假设我们想执行一个UVC的camera设备须要做哪些工作呢? 我简单的查看了几个CM项目的kernel配置文件,发如今这些系统里面的V4L2的驱动配置选项都是打开的,可是CONFIG_USB_VIDEO_CONFIG选项是没有打开的,也就是说在如今CM支持的机型里面默

小游戏二之---------------五子棋

1.五子棋是一比较容易写的小游戏,很适合用来练手,作为练手,不必弄太复杂,所以就不弄电脑AI了,只是玩家之间的对战(AI下次再写). 2.五子棋的难点在于如何判断输赢,其实很简单.每次下棋,就判断该棋子的四个方向,横竖方向,还有两个对角线(分成四个部分,左上,左下,右上,右下)方向是否满足五个棋子. 3.用一个二维数组来表示棋盘(chessBoard[N][N]),值等于0,就表示该位置没有棋子,1表示该位置是玩家1的棋子,2则是玩家2的棋子. 4.运行结果如下: 代码如下(C++),有详细注释

Linux下对inode和块的理解

基本概念 首先讲下inode和块的基本概念.在Linux系统中,文件由元数据和数据块组成.数据块就是多个连续性的扇区(sector),扇区是文件存储的最小单位(每个512字节).块(block)的大小,最常见的是4KB,也就是连续8个sector组成,存储文件数据和目录数据.而元数据用来记录文件的创建者.创建日期.大小等,这种存储文件元数据信息的区域叫做inode,即索引节点. 由于inode也是用来存储文件相关属性信息的,所以也会消耗硬盘空间.具体包含的信息有inode号,文件的字节数.Use

Linux下创建shell、C小程序介绍

1.创建一个shell脚本文件 gedit  hello_shell.sh  ##创建文件 2.###在文件内添加一下内容 #!/bin/bash for  ((i=0;i<10;i++));do echo   "hello shell" done exit 0 3.为文件添加可执行权限 chmod 755 hello_shell.sh 4.执行脚本 ./hello_shell.sh ###创建一个C语言程序"hello world" 1.gedit  hel

linux下模拟CPU占用100%小程序

在做一个测试时,需要模拟服务器CPU占用满的情况,在查阅相关资料后,发现网上程序不太好用, 原文在这:http://www.2cto.com/os/201304/202068.html 优化后如下: #! /bin/sh # filename killcpu.sh if [ $# -ne 1 ] ; then echo "USAGE: $0 <CPUs>|stop" exit 1; fi stop() { while read LINE do kill -9 $LINE e

Linux下安装MySQL以及一些小坑

第一次写博客,各位凑合着看吧(假装有人看). 我这里使用的是centos7. 1.首先打开终端,查看有没有安装过MySQL: [[email protected] lyp]# rpm -qa | grep mysql 若为空则说明没有安装过,若要删除可用yum remove mysql命令. 2.下载mysql的repo源: [[email protected] lyp]# wget http://repo.mysql.com/mysql-community-release-el7-5.noar