1. 程式人生 > >康威生命遊戲 第一部分-基本功能實現(C++ & Windows SDK)

康威生命遊戲 第一部分-基本功能實現(C++ & Windows SDK)

生命遊戲簡介

生命遊戲其實是一個零玩家遊戲,它包括一個二維矩形世界,這個世界中的每個方格居住著一個活著的或死了的細胞。一個細胞在下一個時刻生死取決於相鄰八個方格中活著的或死了的細胞的數量。如果相鄰方格活著的細胞數量過多,這個細胞會因為資源匱乏而在下一個時刻死去;相反,如果周圍活細胞過少,這個細胞會因太孤單而死去。實際中,你可以設定周圍活細胞的數目怎樣時才適宜該細胞的生存。如果這個數目設定過低,世界中的大部分細胞會因為找不到太多的活的鄰居而死去,直到整個世界都沒有生命;如果這個數目設定過高,世界中又會被生命充滿而沒有什麼變化。實際中,這個數目一般選取2或者3;這樣整個生命世界才不至於太過荒涼或擁擠,而是一種動態的平衡。這樣的話,遊戲的規則就是:當一個方格周圍有2或3個活細胞時,方格中的活細胞在下一個時刻繼續存活;即使這個時刻方格中沒有活細胞,在下一個時刻也會“誕生”活細胞。在這個遊戲中,還可以設定一些更加複雜的規則,例如當前方格的狀況不僅由父一代決定,而且還考慮祖父一代的情況。你還可以作為這個世界的上帝,隨意設定某個方格細胞的死活,以觀察對世界的影響。
在遊戲的進行中,雜亂無序的細胞會逐漸演化出各種精緻、有形的結構;這些結構往往有很好的對稱性,而且每一代都在變化形狀。一些形狀已經鎖定,不會逐代變化。有時,一些已經成形的結構會因為一些無序細胞的“入侵”而被破壞。但是形狀和秩序經常能從雜亂中產生出來。

(引用自百度百科)

程式介面

使用的知識點

  1. windows視窗的建立
  2. 按鈕
  3. 定時器
  4. C++基礎記憶體操作

具體實現

整個程式分為兩部分:
1. 底層資料管理
2. 介面描繪和控制邏輯

1, 底層資料管理

為了使邏輯結構可移植, 使用C++編寫了類CWorld, 不涉及任何介面繪圖操作

基本思路:

建立兩塊記憶體分別用於:
1. 記錄當前細胞分佈
2. 記錄下一回合細胞分佈

每一回合(Turn)的計算方法如下:
每個細胞的生死遵循下面的原則:
1. 如果一個細胞周圍有3個細胞為生(一個細胞周圍共有8個細胞),則該細胞為生(即該細胞若原先為死,則轉為生,若原先為生,則保持不變) 。
2. 如果一個細胞周圍有2個細胞為生,則該細胞的生死狀態保持不變;
3. 在其它情況下,該細胞為死(即該細胞若原先為生,則轉為死,若原先為死,則保持不變)

介面程式碼(World.h):

#ifndef _LIFE_GAME_WORLD_H_
#define _LIFE_GAME_WORLD_H_

typedef struct _SCell
{
    int isAlive;
} 
SCell;
/* 注意:
    細胞的座標是從0開始的
*/
class CWorld
{
private:
    int m_width;
    int m_height;
    SCell* m_map1;  //地圖buffer1
    SCell* m_map2;  //地圖buffer2
    SCell* m_cur_map;   //當前地圖
    SCell* m_new_map;   //下一輪使用的地圖
void setCurCell(int x, int y, int isAlive); void setNewCell(int x, int y, int isAlive); int getAroundCellNum(int x, int y); //獲得某個位置周圍存活的細胞數量 int isPosValid(int x, int y); //判定輸入位置是否有效, 1-有效 0-無效 void swapMap(void) { SCell* temp = m_cur_map; m_cur_map = m_new_map; m_new_map = temp; } //交換地圖 SCell* getCell(SCell* buf, int x, int y) { return buf + y * m_width + x; }; //從地圖buffer中獲取某座標的細胞指標 public: CWorld(int width, int height); ~CWorld(); void ramdomInit(void); //隨機初始化地圖 void killAll(void); //殺死所有細胞 void nextTurn(void); //進入下一回合 int getCellAlive(int x, int y); //獲取細胞存活狀態 , 返回值:1-存活, 0-死亡 -1-出錯 int setCellAlive(int x, int y, int isAlive); //設定細胞存活狀態 , 返回值:0-成功 負值-失敗 int getWidth() { return m_width; } //獲得當前地圖寬度 int getHeight() { return m_height; } //獲得當前地圖高度 }; #endif /* _LIFE_GAME_WORLD_H_ */

具體實現程式碼:(World.cpp)

#include <time.h>
#include "World.h"
#include "global.h"


void CWorld::setCurCell(int x, int y, int isAlive)
{
    if (isPosValid(x, y) == 0)
    {
        return;
    }
    else
    {
        SCell* cell = getCell(m_cur_map, x, y);
        if (cell - m_cur_map >= m_width * m_height)
        {
            return;
        }
        cell->isAlive = isAlive;
    }
}

void CWorld::setNewCell(int x, int y, int isAlive)
{
    if (isPosValid(x, y) == 0)
    {
        return;
    }
    else
    {
        SCell* cell = getCell(m_new_map, x, y);
        if (cell - m_new_map >= m_width * m_height)
        {
            return;
        }
        cell->isAlive = isAlive;
    }
}

int CWorld::getAroundCellNum(int x, int y)
{
    int count = 0;

    if (isPosValid(x, y) == 0)
    {   //輸入不合法
        return -1;
    }
    //嘗試目標位置周圍的八個相鄰位置
    for (int i = x - 1; i <= x + 1; ++i)
    {
        for (int j = y - 1; j <= y + 1; ++j)
        {
            if (i == x && j == y)
            {
                continue;
            }
            if (isPosValid(i, j) == 1)
            {
                if (getCellAlive(i, j) == 1)
                {
                    count++;
                }
            }
        }
    }

    return count;
}

int CWorld::isPosValid(int x, int y)
{
    if (x >= m_width || x < 0 || y >= m_height || y < 0)
    {
        return 0;
    }
    return 1;
}

CWorld::CWorld(int width, int height)
{
    m_width = width;
    m_height = height;
    m_map1 = (SCell *) new SCell[m_width * m_height];
    m_map2 = (SCell *) new SCell[m_width * m_height];
    m_cur_map = m_map1;
    m_new_map = m_map2;
    killAll();
}


CWorld::~CWorld()
{
    delete[] m_map1;
    delete[] m_map2;
}

void CWorld::ramdomInit()
{
    killAll();

    srand((unsigned)time(NULL)); //用時間做種,每次產生隨機數不一樣

    for (int i = 0; i < m_width; ++i)
    {
        for (int j = 0; j < m_height; ++j)
        {
            int isAlive = rand() % 2;  //產生0或1的隨機數
            setCurCell(i, j, isAlive);
        }

    }

}

void CWorld::killAll(void)
{
    if (m_cur_map != NULL && m_new_map != NULL)
    {
        for (int i = 0; i < m_width; ++i)
        {
            for (int j = 0; j < m_height; ++j)
            {
                setCurCell(i, j, 0);
                setNewCell(i, j, 0);
            }
        }
    }

}

/*
每個細胞的生死遵循下面的原則:
1. 如果一個細胞周圍有3個細胞為生(一個細胞周圍共有8個細胞),則該細胞為生(即該細胞若原先為死,則轉為生,若原先為生,則保持不變) 。
2. 如果一個細胞周圍有2個細胞為生,則該細胞的生死狀態保持不變;
3. 在其它情況下,該細胞為死(即該細胞若原先為生,則轉為死,若原先為死,則保持不變)
*/
void CWorld::nextTurn(void)
{
    int aroundNum = 0;
    for (int i = 0; i < m_width; ++i)
    {
        for (int j = 0; j < m_height; ++j)
        {
            aroundNum = getAroundCellNum(i, j);
            if (aroundNum == 2)
            {
                setNewCell(i, j, getCellAlive(i, j));
            }
            else if (aroundNum == 3)
            {
                setNewCell(i, j, 1);
            }
            else
            {
                setNewCell(i, j, 0);
            }
        }
    }
    swapMap();
}

int CWorld::getCellAlive(int x, int y)
{
    if (isPosValid(x, y) == 0)
    {
        return -1;
    }
    SCell* cell = getCell(m_cur_map, x, y);
    return cell->isAlive;
}

int CWorld::setCellAlive(int x, int y, int isAlive)
{
    if (isPosValid(x, y) == 0)
    {
        return -1;
    }
    if (isAlive != 0 && isAlive != 1)
    {
        return -2;
    }
    SCell* cell = getCell(m_cur_map, x, y);
    cell->isAlive = isAlive;
    return 0;
}

2, 介面描繪和控制邏輯

main.cpp程式碼如下:

#include <time.h>
#include "global.h"
#include "World.h"

#define WORLD_TIMER_ID (1)  //定時器ID
#define WORLD_TIMER_ELAPSE (1000)   //定時器超時時間

#define RANDOM_BTN_ID (1)
#define START_BTN_ID (2)
#define PAUSE_BTN_ID (3)
#define NEXT_BTN_ID (4)
#define KILL_ALL_BTN_ID (5)

class CWorld *g_world = NULL;   //全域性世界指標

//定時器超時回撥函式
void CALLBACK WorldTimerCallBack(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime);
//描畫函式
void CleanWorld(HDC hdc);
void DrawWorld(CWorld* world, int world_w, int world_h, HDC hdc);
void DrawCell(CWorld* world, HDC hdc);
void DrawGrid(HDC hdc, int w, int h);

void CreateButton(HWND hwnd, HINSTANCE hInstance);

/* 全域性變數定義區 */
char* g_szApplicationName = "LifeGame";
char* g_szWindowClassName = "This Is My Window Class";

/* 訊息回撥函式 */
LRESULT CALLBACK WindowProc(HWND   hwnd,
    UINT   msg,
    WPARAM wParam,
    LPARAM lParam)
{
    //儲存使用者視窗的寬和高
    static int cxClient, cyClient;
    //介面字型寬高
    static int cxChar, cyChar;

    //用於建立後備緩衝
    static HDC      hdcBackBuffer;
    static HBITMAP  hBitmap;
    static HBITMAP  hOldBitmap;

    switch (msg)
    {
    case WM_CREATE:
        {
        RECT rect;

        GetClientRect(hwnd, &rect);

        cxClient = rect.right;
        cyClient = rect.bottom;

        //將視窗移動到螢幕中央
        int scrWidth, scrHeight;
        scrWidth = GetSystemMetrics(SM_CXSCREEN);
        scrHeight = GetSystemMetrics(SM_CYSCREEN);
        GetWindowRect(hwnd, &rect);
        MoveWindow(hwnd, (scrWidth - rect.right) / 2, (scrHeight - rect.bottom) / 2, rect.right - rect.left, rect.bottom - rect.top, FALSE);

        //建立世界和生物
        g_world = new CWorld(WORLD_WIDTH, WORLD_HEIGHT);
        DrawWorld(g_world, WORLD_WIDTH, WORLD_HEIGHT, GetDC(hwnd));
        CreateButton(hwnd, ((LPCREATESTRUCT)lParam)->hInstance);
        EnableWindow(GetDlgItem(hwnd, START_BTN_ID), TRUE); //啟用開始按鈕
        EnableWindow(GetDlgItem(hwnd, PAUSE_BTN_ID), FALSE);    //禁用暫停按鈕
        EnableWindow(GetDlgItem(hwnd, NEXT_BTN_ID), TRUE);  //啟用下一步按鈕
        EnableWindow(GetDlgItem(hwnd, KILL_ALL_BTN_ID), TRUE);  //啟用殺死所有按鈕

        //後備緩衝區相關處理
        hdcBackBuffer = CreateCompatibleDC(NULL);
        HDC hdc = GetDC(hwnd);
        hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
        hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);
        //銷燬處理
        ReleaseDC(hwnd, hdc);

        }
        break;
    case WM_COMMAND:    //按鈕被按下後的響應
    {
        int button_id = LOWORD(wParam);
        switch (button_id)
        {
        case RANDOM_BTN_ID: //隨機初始化按鈕按下
            g_world->ramdomInit();
            DrawWorld(g_world, WORLD_WIDTH, WORLD_HEIGHT, GetDC(hwnd));
            break;
        case START_BTN_ID:  //開始按鈕按下
            SetTimer(hwnd, WORLD_TIMER_ID, WORLD_TIMER_ELAPSE, WorldTimerCallBack); //啟動計時器
            EnableWindow(GetDlgItem(hwnd, RANDOM_BTN_ID), FALSE);   //禁用隨機生成按鈕
            EnableWindow(GetDlgItem(hwnd, START_BTN_ID), FALSE);    //禁用開始按鈕
            EnableWindow(GetDlgItem(hwnd, PAUSE_BTN_ID), TRUE); //啟用暫停按鈕
            EnableWindow(GetDlgItem(hwnd, NEXT_BTN_ID), FALSE); //禁用下一步按鈕
            EnableWindow(GetDlgItem(hwnd, KILL_ALL_BTN_ID), FALSE); //禁用殺死所有按鈕
            break;
        case PAUSE_BTN_ID:  //暫停按鈕按下
            KillTimer(hwnd, WORLD_TIMER_ID);    //銷燬計時器
            EnableWindow(GetDlgItem(hwnd, RANDOM_BTN_ID), TRUE);    //啟用隨機生成按鈕
            EnableWindow(GetDlgItem(hwnd, START_BTN_ID), TRUE); //啟用開始按鈕
            EnableWindow(GetDlgItem(hwnd, PAUSE_BTN_ID), FALSE);    //禁用暫停按鈕
            EnableWindow(GetDlgItem(hwnd, NEXT_BTN_ID), TRUE);  //啟用下一步按鈕
            EnableWindow(GetDlgItem(hwnd, KILL_ALL_BTN_ID), TRUE);  //啟用殺死所有按鈕
            break;
        case NEXT_BTN_ID:   //下一步按鈕按下
            g_world->nextTurn();
            DrawWorld(g_world, WORLD_WIDTH, WORLD_HEIGHT, GetDC(hwnd));
            break;
        case KILL_ALL_BTN_ID:   //殺死所有細胞按鈕按下
            g_world->killAll();
            DrawWorld(g_world, WORLD_WIDTH, WORLD_HEIGHT, GetDC(hwnd));
            break;
        default:
            break;
        }
    }
        break;
    case WM_KEYUP:
        //按下Esc退出
        switch (wParam)
        {
        case VK_ESCAPE:
            PostQuitMessage(0);
            break;
        }
        break;
    case WM_PAINT:
        PAINTSTRUCT ps;
        BeginPaint(hwnd, &ps);
        //將後備緩衝區塗上黑色背景
        BitBlt(hdcBackBuffer,
                0,
                0,
                cxClient,
                cyClient,
                NULL,
                NULL,
                NULL,
                BLACKNESS);

        //描畫世界
        DrawGrid(hdcBackBuffer, WORLD_WIDTH, WORLD_HEIGHT);
        DrawCell(g_world, hdcBackBuffer);

        BitBlt(ps.hdc, 0, 0, cxClient, cyClient, hdcBackBuffer, 0, 0, SRCCOPY);
        EndPaint(hwnd, &ps);
        break;
    case WM_SIZE:
    {
        //變更視窗大小時的處理
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        //改變世界的大小
        //world->setWorldSize(cxClient, cyClient);

        SelectObject(hdcBackBuffer, hOldBitmap);
        DeleteObject(hBitmap);
        HDC hdc = GetDC(hwnd);
        hBitmap = CreateCompatibleBitmap(hdc,
            cxClient,
            cyClient);

        ReleaseDC(hwnd, hdc);
        SelectObject(hdcBackBuffer, hBitmap);
    }
    break;
    case WM_DESTROY:
        //銷燬世界
        delete g_world;

        //清除並銷燬後備緩衝區
        SelectObject(hdcBackBuffer, hOldBitmap);
        DeleteDC(hdcBackBuffer);
        DeleteObject(hBitmap);

        //終了程式,傳送WM_QUIT訊息  
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     szCmdLine,
    int       iCmdShow)
{
    HWND hWnd;  //視窗控制代碼
    WNDCLASSEX winclass;    //視窗類物件

                            //視窗類物件的初始化
    winclass.cbSize = sizeof(WNDCLASSEX);
    winclass.style = CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc = WindowProc;
    winclass.cbClsExtra = 0;
    winclass.cbWndExtra = 0;
    winclass.hInstance = hInstance;
    winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    winclass.hbrBackground = NULL;
    winclass.lpszMenuName = NULL;
    winclass.lpszClassName = g_szWindowClassName;
    winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    //註冊視窗類
    if (!RegisterClassEx(&winclass))
    {
        MessageBox(NULL, "Registration Failed!", "Error", 0);
        return 0;
    }

    //建立視窗  
    hWnd = CreateWindowEx(NULL,                 // extended style
        g_szWindowClassName,  // window class name
        g_szApplicationName,  // window caption
        WS_OVERLAPPEDWINDOW,  // window style
        0,                    // initial x position
        0,                    // initial y position
        WINDOW_WIDTH,         // initial x size
        WINDOW_HEIGHT,        // initial y size
        NULL,                 // parent window handle
        NULL,                 // window menu handle
        hInstance,            // program instance handle
        NULL);                // creation parameters

                              //容錯處理
    if (!hWnd)
    {
        MessageBox(NULL, "CreateWindowEx Failed!", "Error!", 0);
        return 0;
    }

    //顯示視窗
    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

//超時後回撥函式
void CALLBACK WorldTimerCallBack(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
    g_world->nextTurn();
    DrawWorld(g_world, WORLD_WIDTH, WORLD_HEIGHT, GetDC(hwnd));
}

//描畫整個世界
void DrawWorld(CWorld * world, int world_w, int world_h, HDC hdc)
{
    CleanWorld(hdc);
    DrawGrid(hdc, world_w, world_h);
    DrawCell(world, hdc);
}

//將世界塗成黑色(背景色)
void CleanWorld(HDC hdc)
{
    HPEN BlackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    HBRUSH BlackBrush = CreateSolidBrush(RGB(0, 0, 0));
    SelectObject(hdc, BlackPen);
    SelectObject(hdc, BlackBrush);
    Rectangle(hdc, 0, 0, WORLD_WIDTH * CELL_SIZE, WORLD_HEIGHT * CELL_SIZE);
    DeleteObject(BlackPen);
    DeleteObject(BlackBrush);
}

//描畫所有細胞
void DrawCell(CWorld* world, HDC hdc)
{
    HPEN BluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 128));
    HBRUSH BlueBrush = CreateSolidBrush(RGB(0, 0,128));
    SelectObject(hdc, BluePen);
    SelectObject(hdc, BlueBrush);
    for (int i = 0; i < world->getWidth(); ++i)
    {
        for (int j = 0; j < world->getHeight(); ++j)
        {
            if (world->getCellAlive(i, j) == 1)
            {
                Rectangle(hdc, i * CELL_SIZE, j * CELL_SIZE, i * CELL_SIZE + CELL_SIZE, j * CELL_SIZE + CELL_SIZE);
            }
        }
    }

    DeleteObject(BluePen);
    DeleteObject(BlueBrush);
}

//描畫網格
void DrawGrid(HDC hdc, int w, int h)
{
    HPEN GrayPen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
    //HBRUSH GreenBrush = CreateSolidBrush(RGB(0, 255, 0));
    SelectObject(hdc, GrayPen);
    //SelectObject(hdc, GreenBrush);
    for (int i = 0; i <= w; ++i)
    {
        MoveToEx(hdc, i * CELL_SIZE, 0, NULL);
        LineTo(hdc, i * CELL_SIZE, h * CELL_SIZE);
    }
    for (int i = 0; i <= h; ++i)
    {
        MoveToEx(hdc, 0, i * CELL_SIZE, NULL);
        LineTo(hdc, w * CELL_SIZE, i * CELL_SIZE);
    }

    DeleteObject(GrayPen);
    //DeleteObject(GreenBrush);
}

void CreateButton(HWND hwnd, HINSTANCE hInstance)
{
    RECT rect;
    GetClientRect(hwnd, &rect);
    int cxClient = rect.right;

    /* 建立按鈕 */
    int cxChar = LOWORD(GetDialogBaseUnits());
    int cyChar = HIWORD(GetDialogBaseUnits());
    //開始按鈕
    int button_w = cxChar * 12;
    int button_h = cyChar * 2;
    int button_x = cxClient - cxChar * 15;
    int random_btn_y = cyChar * 1;
    int start_btn_y = random_btn_y + button_h + cyChar;
    int pause_btn_y = start_btn_y + button_h + cyChar;
    int next_btn_y = pause_btn_y + button_h + cyChar;
    int kill_all_btn_y = next_btn_y + button_h + cyChar;

    CreateWindow(TEXT("Button"), TEXT("隨機初始化"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        button_x, random_btn_y, button_w, button_h,
        hwnd, (HMENU)RANDOM_BTN_ID,
        hInstance, NULL);
    CreateWindow(TEXT("Button"), TEXT("開始"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        button_x, start_btn_y, button_w, button_h,
        hwnd, (HMENU)START_BTN_ID,
        hInstance, NULL);
    CreateWindow(TEXT("Button"), TEXT("暫停"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        button_x, pause_btn_y, button_w, button_h,
        hwnd, (HMENU)PAUSE_BTN_ID,
        hInstance, NULL);
    CreateWindow(TEXT("Button"), TEXT("下一步"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        button_x, next_btn_y, button_w, button_h,
        hwnd, (HMENU)NEXT_BTN_ID,
        hInstance, NULL);
    CreateWindow(TEXT("Button"), TEXT("殺死所有"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        button_x, kill_all_btn_y, button_w, button_h,
        hwnd, (HMENU)KILL_ALL_BTN_ID,
        hInstance, NULL);
}

最後, 附上global.h程式碼

#pragma once

#include <windows.h>
#include <iostream>

#define WINDOW_WIDTH  800
#define WINDOW_HEIGHT 600
#define WORLD_WIDTH 30
#define WORLD_HEIGHT 20
#define CELL_SIZE 20

程式還有一些地方需要改進, 將在下次進行

相關推薦

生命遊戲 第一部分-基本功能實現C++ & Windows SDK

生命遊戲簡介 生命遊戲其實是一個零玩家遊戲,它包括一個二維矩形世界,這個世界中的每個方格居住著一個活著的或死了的細胞。一個細胞在下一個時刻生死取決於相鄰八個方格中活著的或死了的細胞的數量。如果相鄰方格活著的細胞數量過多,這個細胞會因為資源匱乏而在下一個時

二叉排序樹基本功能實現C++

二叉排序樹(Binary Sort Tree )也稱二叉搜尋樹(Binary Search Tree),以下簡稱BST。 它的特點是左小右大(左子樹小於根,右子樹大於根),令人困惑的是他不允許相等存在,一定要分個高低。這個特點與二叉堆排序有所不同,堆是允許存在相同關鍵字

生命遊戲 Conway's game of life

一、需求描述你的任務是寫一個程式來計算給定起始位置下的下一代康威生命遊戲。遊戲從一個兩維的網格開始,每一個網格有兩種狀態:存活、死亡。網格是有限的,沒有生命可以存活在邊界之外。當計算下一代網格時,需要遵循下述四個規則:1. 任何四周鄰居存活數少於兩個的存活網格將死亡,因為人

生命遊戲的簡單實現

生命遊戲,數學家John Conway發明的一個遊戲,又稱康威生命演化,生命棋,細胞自動機。 康威有許多好玩有趣的發明,最廣為人知的一個是外觀數列(Look-and-Say),這裡不多說,另一個就是生命遊戲(Game-of-Life)。 關於康威,摘錄一段Wikipedia

G. PHP發送郵件功能實現使用163郵箱

wid ucc 認證 bubuko min change hit function chan 第一步我用的是163郵箱發送郵件,做一個嘗試,在嘗試之前,需要要開啟163郵箱的授權碼如圖所示,請記住您的授權碼,將在之後的步驟中用到第二步需要下載一個類PHPMailer,我有這

Android回聲消除功能實現原始碼、編譯

好久沒寫部落格了,今天抽空把這段時間對Android平臺回升消除模組的研究進行一下總結。不要心急哦,下面我會把這個專案的原始碼都開放出來的。 一、回聲消除介紹 傳統的回聲消除都是採用硬體方式,在硬體電路上整合DSP處理晶片,如我們常用的固定電話、手機等都有專門的迴音消除處

wpf中ListView控制元件點選列頭排序功能實現超簡潔實用

 .xaml檔案中的主要程式碼 <ListView Name="lvMeasureData" GridViewColumnHeader.Click="Sort_Click" SelectionChanged="lvMeasureData_SelectionChanged"

自定義UISegmentedControl功能實現使用UIView模擬

自己做專案的過程中遇到過各種各樣的問題,首先我先說一下實現UI設計的一個解決方案: 首先UI設計是這樣的(貼一個做成的圖) 一開始我的想法就是UISegmentedControl來做,但是剛開始做就發現樣式其實跟UI的一點都不一樣,所以我開始思考如何自定義控制元件,所以想

鏈棧的基本操作實現c語言

#include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct linknode {

CocosCreator之KUOKUO帶你做個基於物理的跑酷遊戲第一部分-做個地圖加點盒子

本次引擎2.0.5 編輯工具VSCode 目標:第一部分,做個瓦片地圖,加入物理盒子。   首先開啟這個: 沒有的小夥伴們,百度一下哦。 (可以說是一般的2D遊戲,必備的軟體) 新建一個檔案,裡面的引數根據你手中素材設定。 然後我們添加個素材,瀏

Pat甲級題目刷題分享+演算法筆記提煉 ---------------第一部分 基本資料操作與常用演算法

一、演算法筆記提煉     ·  數學相關      1. 最大公約數+最小公倍數(只需要記住 定理即可)       gcd(a,b) = gcd(b,a%b);   意思是:a與b的最

Java小專案_拼圖遊戲_基本功能實現

前言 利用按鈕元件以及圖片的嵌入完成基本遊戲的搭建,其中按鈕事件監聽是本程式碼的難點。以及事先要規劃好基本模組,包括遊戲的UI視窗、操作模組以及程式碼邏輯設計。 啟動程式碼: package API_UI_拼圖遊戲2; public class start {

視復賽題 ---- 碰撞避免方案1

更新 bsp 題目 比較 toc .html 可能 pro 徹底 題目詳情:http://www.cnblogs.com/wlzy/p/7096182.html 復賽題要求機器人之間不允許發生碰撞和相遇,拿到題目後,大體有以下幾個解題思路: 1.基於側邊停車的碰撞避免算法

unity_小功能實現避免遊戲對象被銷毀時聲音消失

銷毀 碰撞檢測 obj .get pla public tco 發生 cli 在遊戲中我們使用碰撞檢測,當兩個物體發生碰撞時產生聲音音效,代碼如下: 如果使用上述代碼,我們會發現,在腳本中使用AudioSource聲明該聲音,當該物體被銷毀時聲音也會立刻停止。 但是

Guice2.0的變化——第一部分 新的特性

xposed lsmod ide his leo access cep within mat http://superleo.iteye.com/blog/314816 Private Modules PrivateModules 用於創建並不需要對外可見的綁定

WC的基本功能實現.(Java)

編碼 工作 epo 輸入 stage 目前 com 審核 dev 我的GitHub地址:https://github.com/Yuetao1219/lessons WC 項目要求 wc.exe 是一個常見的工具,它能統計文本文件的字符數、單詞數和行數。這個項目要求寫一個命令

視攝像機的實時讀取篇二SDK開發環境配置

參考博主lonelyrains的文章,利用海康SDK+OpenCV,實現了海康攝像機影象實時讀取。篇二介紹海康SDK開發環境配置及相關注意事項。 海康SDK開發環境配置 海康SDK開發環境配置具體步驟類似篇一(http://blog.csdn.net/u011674213/artic

視攝像機的實時讀取篇一OpenCV開發環境配置

參考博主lonelyrains的文章,利用海康SDK+OpenCV,實現了海康攝像機影象實時讀取。篇一介紹環境配置及相關注意事項。 OpenCV開發環境配置 1.下載opencv-2.4.11(其他版本配置過程相似),下載完成後,雙擊檔案會提示解壓到某個地方,解壓完成複製到要配置的目錄下

[效能實驗]INS山寨版(2)-資料庫及基本功能實現

資料庫設計 那麼,轉換為sql語句就是: 注意,都用的是pg資料庫 create or replace function global_temp_update_database() -- returns integer as returns text as $body$

資料結構靜態棧的基本功能實現

/*     2018年10月16日10:08:50       棧的基本功能是 出棧 入棧  遵循”先進後出“原則     所以棧的基本函式可以有棧的初始化 出入棧過程中棧的狀態判斷 是否為空或滿  以及銷燬     實現順序棧的基本運算的演算法     (1)初始化棧