我已经完成了所有的布局,并且编写了大部分代码。但是,我被困在两个地方。
1) 我不太确定如何设置计时器。我是否在 gridwindow 类中正确使用了它?而且,我是否将定时器功能/信号/槽与其他 gridwindow 功能一起正确使用。
2) 在 GridWindow 的 timerFired() 函数中,我无法检查/创建 vector vector 。我在该功能的评论中写出了我正在尝试做的事情。
任何帮助将不胜感激。
主要.cpp
// Main file for running the grid window application.
#include <QApplication>
#include "gridwindow.h"
//#include "timerwindow.h"
#include <stdexcept>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
void Welcome(); // Welcome Function - Prints upon running program; outputs program name, student name/id, class section.
void Rules(); // Rules Function: Prints the rules for Conway's Game of Life.
using namespace std;
// A simple main method to create the window class and then pop it up on the screen.
int main(int argc, char *argv[])
{
Welcome(); // Calls Welcome function to print student/assignment info.
Rules(); // Prints Conway's Game Rules.
QApplication app(argc, argv); // Creates the overall windowed application.
int rows = 25, cols = 35; //The number of rows & columns in the game grid.
GridWindow widget(NULL,rows,cols); // Creates the actual window (for the grid).
widget.show(); // Shows the window on the screen.
return app.exec(); // Goes into visual loop; starts executing GUI.
}
// Welcome Function: Prints my name/id, my class number, the assignment, and the program name.
void Welcome()
{
cout << endl;
cout << "-------------------------------------------------------------------------------------------------" << endl;
cout << "Name/ID - Gabe Audick #7681539807" << endl;
cout << "Class/Assignment - CSCI-102 Disccusion 29915: Homework Assignment #4" << endl;
cout << "-------------------------------------------------------------------------------------------------" << endl << endl;
}
// Rules Function: Prints the rules for Conway's Game of Life.
void Rules()
{
cout << "Welcome to Conway's Game of Life." << endl;
cout << "Game Rules:" << endl;
cout << "\t 1) Any living cell with fewer than two living neighbours dies, as if caused by underpopulation." << endl;
cout << "\t 2) Any live cell with more than three live neighbours dies, as if by overcrowding." << endl;
cout << "\t 3) Any live cell with two or three live neighbours lives on to the next generation." << endl;
cout << "\t 4) Any dead cell with exactly three live neighbours becomes a live cell." << endl << endl;
cout << "Enjoy." << endl << endl;
}
网格单元.h
// A header file for a class representing a single cell in a grid of cells.
#ifndef GRIDCELL_H_
#define GRIDCELL_H_
#include <QPalette>
#include <QColor>
#include <QPushButton>
#include <Qt>
#include <QWidget>
#include <QFrame>
#include <QHBoxLayout>
#include <iostream>
// An enum representing the two different states a cell can have.
enum CellType
{
DEAD, // DEAD = Dead Cell. --> Color = White.
LIVE // LIVE = Living Cell. ---> Color = White.
};
/*
Class: GridCell.
A class representing a single cell in a grid. Each cell is implemented
as a QT QFrame that contains a single QPushButton. The button is sized
so that it takes up the entire frame. Each cell also keeps track of what
type of cell it is based on the CellType enum.
*/
class GridCell : public QFrame
{
Q_OBJECT // Macro allowing us to have signals & slots on this object.
private:
QPushButton* button; // The button inside the cell that gives its clickability.
CellType type; // The type of cell (DEAD or LIVE.)
public slots:
void handleClick(); // Callback for handling a click on the current cell.
void setType(CellType type); // Cell type mutator. Calls the "redrawCell" function.
signals:
void typeChanged(CellType type); // Signal to notify listeners when the cell type has changed.
public:
GridCell(QWidget *parent = NULL); // Constructor for creating a cell. Takes parent widget or default parent to NULL.
virtual ~GridCell(); // Destructor.
void redrawCell(); // Redraws cell: Sets new type/color.
CellType getType() const; //Simple getter for the cell type.
private:
Qt::GlobalColor getColorForCellType(); // Helper method. Returns color that cell should be based from its value.
};
#endif
网格单元.cpp
#include <iostream>
#include "gridcell.h"
#include "utility.h"
using namespace std;
// Constructor: Creates a grid cell.
GridCell::GridCell(QWidget *parent)
: QFrame(parent)
{
this->type = DEAD; // Default: Cell is DEAD (white).
setFrameStyle(QFrame::Box); // Set the frame style. This is what gives each box its black border.
this->button = new QPushButton(this); //Creates button that fills entirety of each grid cell.
this->button->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); // Expands button to fill space.
this->button->setMinimumSize(19,19); //width,height // Min height and width of button.
QHBoxLayout *layout = new QHBoxLayout(); //Creates a simple layout to hold our button and add the button to it.
layout->addWidget(this->button);
setLayout(layout);
layout->setStretchFactor(this->button,1); // Lets the buttons expand all the way to the edges of the current frame with no space leftover
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
connect(this->button,SIGNAL(clicked()),this,SLOT(handleClick())); // Connects clicked signal with handleClick slot.
redrawCell(); // Calls function to redraw (set new type for) the cell.
}
// Basic destructor.
GridCell::~GridCell()
{
delete this->button;
}
// Accessor for the cell type.
CellType GridCell::getType() const
{
return(this->type);
}
// Mutator for the cell type. Also has the side effect of causing the cell to be redrawn on the GUI.
void GridCell::setType(CellType type)
{
this->type = type;
redrawCell();
}
// Handler slot for button clicks. This method is called whenever the user clicks on this cell in the grid.
void GridCell::handleClick()
{ // When clicked on...
if(this->type == DEAD) // If type is DEAD (white), change to LIVE (black).
type = LIVE;
else
type = DEAD; // If type is LIVE (black), change to DEAD (white).
setType(type); // Sets new type (color). setType Calls redrawCell() to recolor.
}
// Method to check cell type and return the color of that type.
Qt::GlobalColor GridCell::getColorForCellType()
{
switch(this->type)
{
default:
case DEAD:
return Qt::white;
case LIVE:
return Qt::black;
}
}
// Helper method. Forces current cell to be redrawn on the GUI. Called whenever the setType method is invoked.
void GridCell::redrawCell()
{
Qt::GlobalColor gc = getColorForCellType(); //Find out what color this cell should be.
this->button->setPalette(QPalette(gc,gc)); //Force the button in the cell to be the proper color.
this->button->setAutoFillBackground(true);
this->button->setFlat(true); //Force QT to NOT draw the borders on the button
}
网格窗口.h
// A header file for a QT window that holds a grid of cells.
#ifndef GRIDWINDOW_H_
#define GRIDWINDOW_H_
#include <vector>
#include <QWidget>
#include <QTimer>
#include <QGridLayout>
#include <QLabel>
#include <QApplication>
#include "gridcell.h"
/*
class GridWindow:
This is the class representing the whole window that comes up when this program runs.
It contains a header section with a title, a middle section of MxN cells and a bottom section with buttons.
*/
class GridWindow : public QWidget
{
Q_OBJECT // Macro to allow this object to have signals & slots.
private:
std::vector<std::vector<GridCell*> > cells; // A 2D vector containing pointers to all the cells in the grid.
QLabel *title; // A pointer to the Title text on the window.
QTimer *timer; // Creates timer object.
public slots:
void handleClear(); // Handler function for clicking the Clear button.
void handleStart(); // Handler function for clicking the Start button.
void handlePause(); // Handler function for clicking the Pause button.
void timerFired(); // Method called whenever timer fires.
public:
GridWindow(QWidget *parent = NULL,int rows=3,int cols=3); // Constructor.
virtual ~GridWindow(); // Destructor.
std::vector<std::vector<GridCell*> >& getCells(); // Accessor for the array of grid cells.
private:
QHBoxLayout* setupHeader(); // Helper function to construct the GUI header.
QGridLayout* setupGrid(int rows,int cols); // Helper function to constructor the GUI's grid.
QHBoxLayout* setupButtonRow(); // Helper function to setup the row of buttons at the bottom.
};
#endif
网格窗口.cpp
#include <iostream>
#include "gridwindow.h"
using namespace std;
// Constructor for window. It constructs the three portions of the GUI and lays them out vertically.
GridWindow::GridWindow(QWidget *parent,int rows,int cols)
: QWidget(parent)
{
QHBoxLayout *header = setupHeader(); // Setup the title at the top.
QGridLayout *grid = setupGrid(rows,cols); // Setup the grid of colored cells in the middle.
QHBoxLayout *buttonRow = setupButtonRow(); // Setup the row of buttons across the bottom.
QVBoxLayout *layout = new QVBoxLayout(); // Puts everything together.
layout->addLayout(header);
layout->addLayout(grid);
layout->addLayout(buttonRow);
setLayout(layout);
}
// Destructor.
GridWindow::~GridWindow()
{
delete title;
}
// Builds header section of the GUI.
QHBoxLayout* GridWindow::setupHeader()
{
QHBoxLayout *header = new QHBoxLayout(); // Creates horizontal box.
header->setAlignment(Qt::AlignHCenter);
this->title = new QLabel("CONWAY'S GAME OF LIFE",this); // Creates big, bold, centered label (title): "Conway's Game of Life."
this->title->setAlignment(Qt::AlignHCenter);
this->title->setFont(QFont("Arial", 32, QFont::Bold));
header->addWidget(this->title); // Adds widget to layout.
return header; // Returns header to grid window.
}
// Builds the grid of cells. This method populates the grid's 2D array of GridCells with MxN cells.
QGridLayout* GridWindow::setupGrid(int rows,int cols)
{
QGridLayout *grid = new QGridLayout(); // Creates grid layout.
grid->setHorizontalSpacing(0); // No empty spaces. Cells should be contiguous.
grid->setVerticalSpacing(0);
grid->setSpacing(0);
grid->setAlignment(Qt::AlignHCenter);
for(int i=0; i < rows; i++) //Each row is a vector of grid cells.
{
std::vector<GridCell*> row; // Creates new vector for current row.
cells.push_back(row);
for(int j=0; j < cols; j++)
{
GridCell *cell = new GridCell(); // Creates and adds new cell to row.
cells.at(i).push_back(cell);
grid->addWidget(cell,i,j); // Adds to cell to grid layout. Column expands vertically.
grid->setColumnStretch(j,1);
}
grid->setRowStretch(i,1); // Sets row expansion horizontally.
}
return grid; // Returns grid.
}
// Builds footer section of the GUI.
QHBoxLayout* GridWindow::setupButtonRow()
{
QHBoxLayout *buttonRow = new QHBoxLayout(); // Creates horizontal box for buttons.
buttonRow->setAlignment(Qt::AlignHCenter);
// Clear Button - Clears cell; sets them all to DEAD/white.
QPushButton *clearButton = new QPushButton("CLEAR");
clearButton->setFixedSize(100,25);
connect(clearButton, SIGNAL(clicked()), this, SLOT(handleClear()));
buttonRow->addWidget(clearButton);
// Start Button - Starts game when user clicks. Or, resumes game after being paused.
QPushButton *startButton = new QPushButton("START/RESUME");
startButton->setFixedSize(100,25);
connect(startButton, SIGNAL(clicked()), this, SLOT(handleStart()));
buttonRow->addWidget(startButton);
// Pause Button - Pauses simulation of game.
QPushButton *pauseButton = new QPushButton("PAUSE");
pauseButton->setFixedSize(100,25);
connect(pauseButton, SIGNAL(clicked()), this, SLOT(handlePause()));
buttonRow->addWidget(pauseButton);
// Quit Button - Exits program.
QPushButton *quitButton = new QPushButton("EXIT");
quitButton->setFixedSize(100,25);
connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
buttonRow->addWidget(quitButton);
return buttonRow; // Returns bottom of layout.
}
/*
SLOT method for handling clicks on the "clear" button.
Receives "clicked" signals on the "Clear" button and sets all cells to DEAD.
*/
void GridWindow::handleClear()
{
for(unsigned int row=0; row < cells.size(); row++) // Loops through current rows' cells.
{
for(unsigned int col=0; col < cells[row].size(); col++)
{
GridCell *cell = cells[row][col]; // Grab the current cell & set its value to dead.
cell->setType(DEAD);
}
}
}
/*
SLOT method for handling clicks on the "start" button.
Receives "clicked" signals on the "start" button and begins game simulation.
*/
void GridWindow::handleStart()
{
this->timer = new QTimer(this); // Creates new timer.
connect(this->timer, SIGNAL(timeout()), this, SLOT(timerFired())); // Connect "timerFired" method class to the "timeout" signal fired by the timer.
this->timer->start(500); // Timer to fire every 500 milliseconds.
}
/*
SLOT method for handling clicks on the "pause" button.
Receives "clicked" signals on the "pause" button and stops the game simulation.
*/
void GridWindow::handlePause()
{
this->timer->stop(); // Stops the timer.
delete this->timer; // Deletes timer.
}
// Accessor method - Gets the 2D vector of grid cells.
std::vector<std::vector<GridCell*> >& GridWindow::getCells()
{
return this->cells;
}
void GridWindow::timerFired()
{
// I'm not sure how to write this code.
// I want to take the original vector-vector, and also make a new, empty vector-vector of the same size.
// I would then go through the code below with the original vector, and apply the rules to the new vector-vector.
// Finally, I would make the new vector-vecotr the original vector-vector. (That would be one step in the simulation.)
cout << cells[1][2];
/*
for (unsigned int m = 0; m < original.size(); m++)
{
for (unsigned int n = 0; n < original.at(m).size(); n++)
{
unsigned int neighbors = 0; //Begin counting number of neighbors.
if (original[m-1][n-1].getType() == LIVE) // If a cell next to [i][j] is LIVE, add one to the neighbor count.
neighbors += 1;
if (original[m-1][n].getType() == LIVE)
neighbors += 1;
if (original[m-1][n+1].getType() == LIVE)
neighbors += 1;
if (original[m][n-1].getType() == LIVE)
neighbors += 1;
if (original[m][n+1].getType() == LIVE)
neighbors += 1;
if (original[m+1][n-1].getType() == LIVE)
neighbors += 1;
if (original[m+1][n].getType() == LIVE)
neighbors += 1;
if (original[m+1][n+1].getType() == LIVE)
neighbors += 1;
if (original[m][n].getType() == LIVE && neighbors < 2) // Apply game rules to cells: Create new, updated grid with the roundtwo vector.
roundtwo[m][n].setType(LIVE);
else if (original[m][n].getType() == LIVE && neighbors > 3)
roundtwo[m][n].setType(DEAD);
else if (original[m][n].getType() == LIVE && (neighbors == 2 || neighbors == 3))
roundtwo[m][n].setType(LIVE);
else if (original[m][n].getType() == DEAD && neighbors == 3)
roundtwo[m][n].setType(LIVE);
}
}*/
}
最佳答案
我看来定时器设置正确。
对于 timerFired() 函数,我不会创建 GridCell 对象的临时矩阵,而只是创建一个临时标志矩阵,指示单元格是否处于事件状态或不是。这些标志实际上是您函数中的所有更改,因此只需暂时存储新标志,然后将它们设置在原始网格单元上,以节省创建临时单元矩阵所需的所有额外内存和分配时间。这是一个例子:
//Store flags that represent whether the new grid cells will be live or not
vector< vector<bool> > is_live(cells.size());
for(int m=0; m<cells.size(); m++)
{
is_live.at(m).resize(cells.at(m).size());
for(int n=0; n<cells.at(m).size(); n++)
{
//count neighbors
unsigned int neighbors = 0;
for(int i=-1; i<=1; i++)
{
for(int j=-1; j<=1; j++)
{
neighbors += static_cast<int>(
cells[m+i][n+j]->getType() == LIVE);
}
}
//we counted the current cell when counting the neighbors so
//subtract it back off if needed.
neighbors -= static_cast<int>(cells[m][n]->getType() == LIVE);
//Set the type to the original value
is_live[m][n] = cells[m][n]->getType() == LIVE;
//change it based on the neighbor count.
//Some of your logic around here seemed repetitive so I
//did it differently. You may want to change it back
//if you had a specific purpose for the way you did it
is_live[m][n] = (is_live[m][n] && neighbors <= 3) ||
(!is_live[m][n] && neighbors == 3);
}
}
//Set the cell types based on the is_live flags.
for(int m=0; m<cells.size(); m++)
{
for(int n=0; n<cells.at(m).size(); n++)
cells[m][n]->setType(is_live[m][n] ? LIVE : DEAD);
}
注意:我没有编译或测试它,所以不能保证。
关于c++ - 康威的生命游戏 - C++ 和 Qt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2596971/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t
我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?