java初心者です、テトリスを作っているのですが落ちてきたブロックがつみあがると外壁と同じ色になって困っています。どうしたら外壁と落ちてきたブロックの色を分けて描画できるのでしょうか?ご教授願います。
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 6,094
ボールドテキストjava初心者です。
テトリスを作っているんですが、このコードでブロックが外壁まで落ちてきたときに外壁と同じ色になってしまいます。外壁の色を赤、落ちてくるブロックをランダムな色として設定し、ブロックが落ちたときに外壁の色と同化せず落ちてきた色のままつみあげるにはどうしたらいいのでしょうか?
かなり悩んでいます。
``
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class Tetris extends Applet implements KeyListener{
public static final int HEIGHT=23;//縦
public static final int WIDTH=14;//横
public static final int SIZE =30;//ブロックの大きさ
private int [][]field=new int[WIDTH][HEIGHT];
public static final Color[] COLSELECT={Color.pink,Color.black,Color.green,Color.yellow,Color.gray,Color.MAGENTA,Color.orange};//色の選択
public static final int BLANK=0;
public static final int WALL=1;
Point Point = new Point(5,0);//初期配置座標
Random rnd = new Random();
int select =rnd.nextInt(7);
Color nextColor=COLSELECT[select];
/**
* 初期化処理
*/
@Override
public void init(){
addKeyListener(this);
for(int y=0;y<HEIGHT;y++) {
for(int x=0;x<WIDTH; x++) {
field[x][y]=BLANK;
}
}
for (int x=0;x<WIDTH;x++) {
field[x][HEIGHT-1]=WALL;
}
for(int y=0;y<HEIGHT;y++) {
field[0][y]=WALL;
field[WIDTH-1][y]=WALL;
}
}
/**
* @param e KeyEventオブジェクト
*/
@Override
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();//キーの情報を取得
if (key==KeyEvent.VK_LEFT){// 方向キー左が押されたとき
if(field[Point.x-1][Point.y]==BLANK){
Point.x--;
repaint();
}
}else if (key==KeyEvent.VK_RIGHT){// 方向キー右が押されたとき
if(field[Point.x+1][Point.y]==BLANK){
Point.x++ ;
repaint();
}
}else if (key==KeyEvent.VK_DOWN){// 方向キー下が押されたとき
if(field[Point.x][Point.y+1]==BLANK){
Point.y++ ;
repaint();
}else{
field[Point.x][Point.y]=WALL;
Block();
Point = new Point(5,0);// ブロック初期座標
repaint();
}
}
}
@Override
public void keyReleased(KeyEvent e){
}
@Override
public void keyTyped(KeyEvent e){
}
/**
*@param g Graphicsオブジェクト
*/
@Override
public void paint(Graphics g){
if(field[Point.x][Point.y]==BLANK){
g.setColor(nextColor);
g.fillRect(Point.x*SIZE,Point.y*SIZE,SIZE,SIZE);
}
// 外壁
for(int i = 0;i <WIDTH;i++){
for(int j = 0;j <HEIGHT;j++){
if(field[i][j]!=BLANK){
g.setColor(COLSELECT[field[i][j]]);
//g.setColor(Color.red);
g.fillRect(i*SIZE,j*SIZE,SIZE,SIZE);
}
}
}
g.setColor(Color.black);
for(int i=0;i<=HEIGHT;i++){
g.drawLine(0,i*SIZE,WIDTH*SIZE,i*SIZE);
}
for(int j=0;j<=WIDTH;j++){
g.drawLine(j*SIZE,0,j*SIZE,HEIGHT*SIZE);
}
}
public void Block(){
Random rnd = new Random();
int select =rnd.nextInt(7);
nextColor=COLSELECT[select];
COLSELECT[field[Point.x][Point.y]]=COLSELECT[select];
}
}
テトリスを作っているんですが、このコードでブロックが外壁まで落ちてきたときに外壁と同じ色になってしまいます。外壁の色を赤、落ちてくるブロックをランダムな色として設定し、ブロックが落ちたときに外壁の色と同化せず落ちてきた色のままつみあげるにはどうしたらいいのでしょうか?
かなり悩んでいます。
``
コード
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class Tetris extends Applet implements KeyListener{
public static final int HEIGHT=23;//縦
public static final int WIDTH=14;//横
public static final int SIZE =30;//ブロックの大きさ
private int [][]field=new int[WIDTH][HEIGHT];
public static final Color[] COLSELECT={Color.pink,Color.black,Color.green,Color.yellow,Color.gray,Color.MAGENTA,Color.orange};//色の選択
public static final int BLANK=0;
public static final int WALL=1;
Point Point = new Point(5,0);//初期配置座標
Random rnd = new Random();
int select =rnd.nextInt(7);
Color nextColor=COLSELECT[select];
/**
* 初期化処理
*/
@Override
public void init(){
addKeyListener(this);
for(int y=0;y<HEIGHT;y++) {
for(int x=0;x<WIDTH; x++) {
field[x][y]=BLANK;
}
}
for (int x=0;x<WIDTH;x++) {
field[x][HEIGHT-1]=WALL;
}
for(int y=0;y<HEIGHT;y++) {
field[0][y]=WALL;
field[WIDTH-1][y]=WALL;
}
}
/**
* @param e KeyEventオブジェクト
*/
@Override
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();//キーの情報を取得
if (key==KeyEvent.VK_LEFT){// 方向キー左が押されたとき
if(field[Point.x-1][Point.y]==BLANK){
Point.x--;
repaint();
}
}else if (key==KeyEvent.VK_RIGHT){// 方向キー右が押されたとき
if(field[Point.x+1][Point.y]==BLANK){
Point.x++ ;
repaint();
}
}else if (key==KeyEvent.VK_DOWN){// 方向キー下が押されたとき
if(field[Point.x][Point.y+1]==BLANK){
Point.y++ ;
repaint();
}else{
field[Point.x][Point.y]=WALL;
Block();
Point = new Point(5,0);// ブロック初期座標
repaint();
}
}
}
@Override
public void keyReleased(KeyEvent e){
}
@Override
public void keyTyped(KeyEvent e){
}
/**
*@param g Graphicsオブジェクト
*/
@Override
public void paint(Graphics g){
if(field[Point.x][Point.y]==BLANK){
g.setColor(nextColor);
g.fillRect(Point.x*SIZE,Point.y*SIZE,SIZE,SIZE);
}
// 外壁
for(int i = 0;i <WIDTH;i++){
for(int j = 0;j <HEIGHT;j++){
if(field[i][j]!=BLANK){
g.setColor(COLSELECT[field[i][j]]);
//g.setColor(Color.red);
g.fillRect(i*SIZE,j*SIZE,SIZE,SIZE);
}
}
}
g.setColor(Color.black);
for(int i=0;i<=HEIGHT;i++){
g.drawLine(0,i*SIZE,WIDTH*SIZE,i*SIZE);
}
for(int j=0;j<=WIDTH;j++){
g.drawLine(j*SIZE,0,j*SIZE,HEIGHT*SIZE);
}
}
public void Block(){
Random rnd = new Random();
int select =rnd.nextInt(7);
nextColor=COLSELECT[select];
COLSELECT[field[Point.x][Point.y]]=COLSELECT[select];
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
問題の直接の原因は、以下の3点にあります。
1.
2.
3.
たとえば以下のようにすると、これらのミスを防ぐことができます。
-
-
- 直接は関係ありませんが、インスタンスフィールド(
それと、これはミスではないですが、
他にもいくつかありますが、直接コードを見てみてください。
1.
Block
メソッドのCOLSELECT
配列を書き換えているところがありますが、この配列は書き換えてはいけないはずです。
2.
Block
メソッドのint select =rnd.nextInt(7)
は、ローカル変数でなく、フィールドのselect
に設定すべきでは?
3.
keyPressed
のVK_DOWN
かつ下のブロックがBLANK
でないときの処理は、field
に設定するのはWALL
ではなく、select
では?
たとえば以下のようにすると、これらのミスを防ぐことができます。
-
COLSELECT
配列は、Arrays.asList
などを使って、読み取り専用のList
にしておくと、誤ってCOLSELECT
を変更することができなくなります。
-
nextColor
フィールドは冗長なので、無い方が良いでしょう。
- 直接は関係ありませんが、インスタンスフィールド(
field
変数でなく)を初期化している箇所は、次のパーツを表示する時にも同じような処理をしていますので、メソッドにまとめてinit
から呼ぶようにしたほうが良いと思います。
それと、これはミスではないですが、
Random
はRandom#setSeed
を使って毎回ランダム値が変わるようにした方が良いと思います。
他にもいくつかありますが、直接コードを見てみてください。
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class Tetris extends Applet implements KeyListener {
public static final int HEIGHT = 23;//縦
public static final int WIDTH = 14;//横
public static final int SIZE = 30;//ブロックの大きさ
public static final int BLANK = 0;
public static final int WALL = 1;
// ★読取専用Listにする ★0はブランク(WHITE)用
public static final List<Color> COLSELECT = Arrays.asList(Color.WHITE, Color.BLACK, Color.PINK, Color.GREEN,
Color.YELLOW, Color.GRAY, Color.MAGENTA, Color.ORANGE);//色の選択
private int[][] field = new int[WIDTH][HEIGHT];
private Random rnd = new Random();
// ★ブロック初期化は initBlock で
Point Point;
int select;
/**
* 初期化処理
*/
@Override
public void init() {
addKeyListener(this);
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
field[x][y] = BLANK;
}
}
for (int x = 0; x < WIDTH; x++) {
field[x][HEIGHT - 1] = WALL;
}
for (int y = 0; y < HEIGHT; y++) {
field[0][y] = WALL;
field[WIDTH - 1][y] = WALL;
}
rnd.setSeed(System.currentTimeMillis()); // Seedのセット
initBlock();
}
private void initBlock() {
Point = new Point(5, 0);//初期配置座標
select = rnd.nextInt(7) + 1; // ★0はブランク(WHITE)用
}
/**
* @param e KeyEventオブジェクト
*/
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();//キーの情報を取得
if (key == KeyEvent.VK_LEFT) {// 方向キー左が押されたとき
if (field[Point.x - 1][Point.y] == BLANK) {
Point.x--;
repaint();
}
}
else if (key == KeyEvent.VK_RIGHT) {// 方向キー右が押されたとき
if (field[Point.x + 1][Point.y] == BLANK) {
Point.x++;
repaint();
}
}
else if (key == KeyEvent.VK_DOWN) {// 方向キー下が押されたとき
if (field[Point.x][Point.y + 1] == BLANK) {
Point.y++;
repaint();
}
else {
field[Point.x][Point.y] = select; // ★WALLでなくselect
// Block();
// Point = new Point(5, 0);// ブロック初期座標
// ★ブロック初期化は initBlock で
initBlock();
repaint();
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
/**
*@param g Graphicsオブジェクト
*/
@Override
public void paint(Graphics g) {
if (field[Point.x][Point.y] == BLANK) {
g.setColor(COLSELECT.get(select));
g.fillRect(Point.x * SIZE, Point.y * SIZE, SIZE, SIZE);
}
// 外壁
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
int v = field[i][j];
if (v != BLANK) {
g.setColor(COLSELECT.get(v));
//g.setColor(Color.red);
g.fillRect(i * SIZE, j * SIZE, SIZE, SIZE);
}
}
}
g.setColor(Color.black);
for (int i = 0; i <= HEIGHT; i++) {
g.drawLine(0, i * SIZE, WIDTH * SIZE, i * SIZE);
}
for (int j = 0; j <= WIDTH; j++) {
g.drawLine(j * SIZE, 0, j * SIZE, HEIGHT * SIZE);
}
}
// ★ブロック初期化は initBlock で
// public void Block() {
// Random rnd = new Random();
// int select =rnd.nextInt(7);
// nextColor=COLSELECT.get(select);
// COLSELECT[field[Point.x][Point.y]]=COLSELECT[select];
// }
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2014/12/18 14:20
回答者様のおかげでうまく処理を行うことができました。
回答者様のコードと見比べると自分のコードはかなり冗長になっており書き換えてはいけないところまで書き換えてしまい思ったとおりの処理ができていませんでした。コードを書くときは中のコードをすっきりと書けるように勉強していきます!お答えいただき誠にありがとうございます!