Kode berikut tidak berfungsi seperti yang saya inginkan, tetapi jelek, berlebihan, atau beberapa hal lainnya. Saya telah melihat formula dan berusaha menulis beberapa solusi, tetapi saya berakhir dengan jumlah pernyataan yang sama.
Apakah ada jenis rumus matematika yang akan bermanfaat bagi saya dalam hal ini atau 16 jika pernyataan diterima?
Untuk menjelaskan kode, ini untuk jenis permainan berbasis giliran simultan .. dua pemain masing-masing memiliki empat tombol aksi dan hasilnya berasal dari sebuah array (0-3), tetapi variabel 'satu' & 'dua' dapat berupa ditugaskan apa pun jika ini membantu. Hasilnya adalah, 0 = tidak menang, 1 = p1 menang, 2 = p2 menang, 3 = keduanya menang.
public int fightMath(int one, int two) {
if(one == 0 && two == 0) { result = 0; }
else if(one == 0 && two == 1) { result = 0; }
else if(one == 0 && two == 2) { result = 1; }
else if(one == 0 && two == 3) { result = 2; }
else if(one == 1 && two == 0) { result = 0; }
else if(one == 1 && two == 1) { result = 0; }
else if(one == 1 && two == 2) { result = 2; }
else if(one == 1 && two == 3) { result = 1; }
else if(one == 2 && two == 0) { result = 2; }
else if(one == 2 && two == 1) { result = 1; }
else if(one == 2 && two == 2) { result = 3; }
else if(one == 2 && two == 3) { result = 3; }
else if(one == 3 && two == 0) { result = 1; }
else if(one == 3 && two == 1) { result = 2; }
else if(one == 3 && two == 2) { result = 3; }
else if(one == 3 && two == 3) { result = 3; }
return result;
}
if-statement
math
formula
TomFirth
sumber
sumber
f(a, b)
yang menghasilkan jawaban dalam kasus umum? Anda belum menjelaskan logika perhitungan karena itu semua jawabannya hanya lipstik pada seekor babi. Saya akan mulai dengan serius memikirkan kembali logika program Anda, menggunakanint
flags untuk tindakan sangat ketinggalan jaman.enum
s dapat berisi logika dan deskriptif, ini akan memungkinkan Anda untuk menulis kode Anda dengan cara yang lebih modern.Jawaban:
Jika Anda tidak bisa membuat formula, Anda bisa menggunakan tabel untuk hasil yang terbatas:
sumber
IndexOutOfBoundsException
tetap melemparkan jika satu atau lebih indeks berada di luar batas.i
/j
/k
konvensi untuk variabel loop), bernama konstanta, mengatur kode saya dengan cara yang dapat dibaca, dll., Tetapi ketika variabel dan nama fungsi mulai mengambil lebih dari 20 karakter setiap saya menemukan itu benar-benar mengarah pada kode yang kurang mudah dibaca. Pendekatan saya yang biasa adalah mencoba untuk kode yang komprehensif tetapi ringkas dengan komentar di sana-sini untuk menjelaskan mengapa kode tersebut terstruktur seperti itu (vs bagaimana). Menempatkan mengapa dalam nama hanya mengacaukan segalanya.Karena kumpulan data Anda sangat kecil, Anda dapat memampatkan semuanya menjadi 1 bilangan bulat panjang dan mengubahnya menjadi rumus
Varian bitwise lainnya:
Ini memanfaatkan fakta bahwa semuanya adalah kelipatan dari 2
The Origin of the Magic Constant
Apa yang bisa kukatakan? Dunia membutuhkan sihir, kadang-kadang kemungkinan sesuatu membutuhkan penciptaannya.
Inti dari fungsi yang memecahkan masalah OP adalah peta dari 2 angka (satu, dua), domain {0,1,2,3} hingga rentang {0,1,2,3}. Setiap jawaban telah mendekati cara mengimplementasikan peta itu.
Juga, Anda dapat melihat dalam sejumlah jawaban pernyataan kembali masalah sebagai peta 1 basis 2-digit 4 nomor N (satu, dua) di mana satu adalah digit 1, dua adalah digit 2, dan N = 4 * satu + dua; N = {0,1,2, ..., 15} - enam belas nilai yang berbeda, itu penting. Output dari fungsi adalah satu basis 1 digit 4 angka {0,1,2,3} - 4 nilai yang berbeda, juga penting.
Sekarang, nomor basis 4 digit 1 dapat dinyatakan sebagai nomor basis 2 digit 2; {0,1,2,3} = {00,01,10,11}, sehingga setiap output dapat dikodekan dengan hanya 2 bit. Dari atas, hanya ada 16 output yang berbeda yang mungkin, jadi 16 * 2 = 32 bit adalah semua yang diperlukan untuk menyandikan seluruh peta; ini semua bisa masuk ke dalam 1 integer.
Konstanta M adalah penyandian peta m di mana m (0) dikodekan dalam bit M [0: 1], m (1) dikodekan dalam bit M [2: 3], dan m (n) dikodekan dalam bit M [n * 2: n * 2 + 1].
Yang tersisa hanyalah pengindeksan dan mengembalikan bagian kanan konstanta, dalam hal ini Anda dapat menggeser M kanan 2 * N kali dan mengambil 2 bit paling tidak signifikan, yaitu (M >> 2 * N) & 0x3. Ekspresi (satu << 3) dan (dua << 1) hanya mengalikan hal sambil mencatat bahwa 2 * x = x << 1 dan 8 * x = x << 3.
sumber
Saya tidak suka solusi yang disajikan kecuali untuk JAB. Tidak ada yang lain membuatnya mudah untuk membaca kode dan memahami apa yang sedang dihitung .
Inilah cara saya akan menulis kode ini - Saya hanya tahu C #, bukan Java, tetapi Anda mendapatkan gambar:
Sekarang jauh lebih jelas apa yang sedang dihitung di sini: ini menekankan bahwa kita menghitung siapa yang terkena serangan apa, dan mengembalikan kedua hasil.
Namun ini bisa menjadi lebih baik; array Boolean agak buram. Saya suka pendekatan pencarian tabel tetapi saya akan cenderung untuk menuliskannya sedemikian rupa sehingga memperjelas apa yang dimaksud dengan semantik game yang dimaksud. Artinya, daripada "serangan nol dan pertahanan satu hasil tanpa pukulan", alih-alih menemukan cara untuk membuat kode lebih jelas menyiratkan "serangan tendangan rendah dan pertahanan blok rendah menghasilkan tanpa serangan". Buat kodenya mencerminkan logika bisnis gim.
sumber
Anda dapat membuat matriks yang berisi hasil
Saat Anda ingin mendapatkan nilai, Anda akan menggunakannya
sumber
Orang lain telah menyarankan ide awal saya, metode matriks, tetapi selain mengkonsolidasikan pernyataan if, Anda dapat menghindari sebagian dari apa yang Anda miliki dengan memastikan argumen yang disediakan berada dalam kisaran yang diharapkan dan dengan menggunakan pengembalian di tempat (beberapa pengkodean standar yang saya lihat menerapkan satu titik keluar untuk fungsi, tetapi saya telah menemukan bahwa banyak pengembalian sangat berguna untuk menghindari pengkodean panah dan dengan prevalensi pengecualian di Jawa tidak ada banyak gunanya secara ketat menegakkan aturan seperti itu pula karena setiap pengecualian yang tidak tertangkap yang dilemparkan ke dalam metode ini mungkin adalah titik keluar). Pernyataan peralihan yang bersarang adalah suatu kemungkinan, tetapi untuk rentang nilai yang kecil yang Anda periksa di sini, saya menemukan jika pernyataan menjadi lebih ringkas dan tidak cenderung menghasilkan banyak perbedaan kinerja,
Ini akhirnya menjadi kurang dapat dibaca daripada mungkin karena ketidakteraturan bagian-bagian dari pemetaan input-> hasil. Saya lebih menyukai gaya matriks karena kesederhanaannya dan bagaimana Anda dapat mengatur matriks agar masuk akal secara visual (meskipun itu sebagian dipengaruhi oleh ingatan saya akan peta Karnaugh):
Pembaruan: Mengingat Anda menyebutkan pemblokiran / pemukulan, berikut ini adalah perubahan yang lebih radikal pada fungsi yang menggunakan tipe enumerated properti-holding yang disebutkan untuk input dan hasilnya dan juga memodifikasi hasil sedikit untuk memperhitungkan pemblokiran, yang akan menghasilkan lebih banyak fungsi yang dapat dibaca.
Anda bahkan tidak perlu mengubah fungsi itu sendiri jika Anda ingin menambahkan blok / serangan yang lebih tinggi, hanya enum; menambahkan jenis gerakan tambahan mungkin akan membutuhkan modifikasi fungsi. Juga,
EnumSet
s mungkin lebih dapat diperluas daripada menggunakan enum tambahan sebagai properti enum utama, misalnyaEnumSet<Move> attacks = EnumSet.of(Move.ATTACK_HIGH, Move.ATTACK_LOW, ...);
dan kemudianattacks.contains(move)
daripadamove.type == MoveType.ATTACK
, meskipun menggunakanEnumSet
s mungkin akan sedikit lebih lambat daripada langsung sama dengan cek.Untuk kasus di mana blok yang berhasil menghasilkan penghitung, Anda dapat menggantinya
if (one.height == two.height) return LandedHit.NEITHER;
denganJuga, mengganti beberapa
if
pernyataan dengan penggunaan operator ternary (boolean_expression ? result_if_true : result_if_false
) dapat membuat kode lebih kompak (misalnya, kode di blok sebelumnya akan menjadireturn one.isAttack() ? LandedHit.PLAYER_TWO : LandedHit.PLAYER_ONE;
), tetapi itu dapat menyebabkan oneliners yang lebih sulit dibaca sehingga saya tidak akan ' t merekomendasikannya untuk percabangan yang lebih kompleks.sumber
one
dantwo
digunakan kembali sebagai titik awal pada spritesheet saya. Meskipun tidak memerlukan banyak kode tambahan untuk memungkinkannya.EnumMap
kelas yang bisa Anda gunakan untuk memetakan enum ke offset integer Anda (Anda juga bisa menggunakan nilai ordinal anggota enum secara langsung, misalnyaMove.ATTACK_HIGH.ordinal()
akan0
,Move.ATTACK_LOW.ordinal()
akan1
, dll., Tapi itu lebih rapuh / kurang fleksibel daripada secara eksplisit mengasosiasikan setiap anggota dengan nilai sebagai menambahkan nilai enum di antara yang sudah ada akan membuang hitungan, yang tidak akan menjadi kasus denganEnumMap
.)attack(against)
metode keMove
enum, mengembalikan HIT ketika langkah itu adalah serangan yang berhasil, BACKFIRE ketika langkah itu adalah serangan yang diblokir, dan TIDAK ADA saat itu bukan serangan. Dengan cara ini Anda dapat mengimplementasikannya secara umum (public boolean attack(Move other) { if this.isAttack() return (other.isAttack() || other.height != this.height) ? HIT : BACKFIRE; return NOTHING; }
), dan menimpanya pada gerakan tertentu saat dibutuhkan (gerakan lemah yang dapat diblokir oleh blok mana pun, serangan yang tidak pernah menjadi bumerang, dll.)Mengapa tidak menggunakan array?
Saya akan mulai dari awal. Saya melihat sebuah pola, nilainya berubah dari 0 menjadi 3 dan Anda ingin menangkap semua nilai yang mungkin. Ini meja Anda:
ketika kita melihat tabel biner yang sama ini kita melihat hasil berikut:
Sekarang mungkin Anda sudah melihat beberapa pola tetapi ketika saya menggabungkan nilai satu dan dua, saya melihat bahwa Anda menggunakan semua nilai 0000, 0001, 0010, ..... 1110 dan 1111. Sekarang mari kita gabungkan nilai satu dan dua untuk membuat satu 4 bit integer.
Ketika kami menerjemahkan ini kembali ke nilai desimal, kami melihat array nilai yang sangat memungkinkan di mana gabungan satu dan dua dapat digunakan sebagai indeks:
Array kemudian
{0, 0, 1, 2, 0, 0, 2, 1, 2, 1, 3, 3, 2, 1, 3, 3}
, di mana indeksnya hanya satu dan dua digabungkan.Saya bukan programmer Java, tetapi Anda bisa menghilangkan semua pernyataan if dan menuliskannya sebagai berikut:
Saya tidak tahu apakah bitshift 2 lebih cepat dari multiplikasi. Tapi itu bisa dicoba.
sumber
Ini menggunakan sedikit bitmagic (Anda sudah melakukannya dengan memegang dua bit informasi (rendah / tinggi & serang / blok) dalam satu integer):
Saya belum menjalankannya, hanya mengetiknya di sini, tolong klik dua kali.Idenya pasti berhasil. EDIT: Sekarang diuji untuk setiap input, berfungsi dengan baik.Atau haruskah saya menyarankan untuk memisahkan dua bit informasi menjadi variabel yang terpisah? Kode sebagian besar didasarkan pada operasi bit seperti ini di atas biasanya sangat sulit untuk dipelihara.
sumber
return ((one ^ two) & 2) == 0 ? (one & 2) / 2 * 3 : ((one & 2) / 2 ^ ((one ^ two) & 1)) + 1;
Sejujurnya, setiap orang memiliki gaya kode mereka sendiri. Saya tidak akan berpikir kinerja akan terlalu terpengaruh. Jika Anda memahami ini lebih baik daripada menggunakan versi sakelar, teruskan menggunakan ini.
Anda bisa membuat sarang jika, sehingga berpotensi akan ada sedikit peningkatan kinerja untuk yang terakhir jika memeriksa karena tidak akan melalui banyak jika pernyataan. Tetapi dalam konteks Anda tentang kursus dasar Java mungkin tidak akan menguntungkan.
Jadi, bukannya ...
Kamu akan melakukan ...
Dan cukup format ulang sesuai keinginan Anda.
Ini tidak membuat kode terlihat lebih baik, tetapi saya pikir berpotensi mempercepatnya.
sumber
Mari kita lihat apa yang kita ketahui
1: jawaban Anda simetris untuk P1 (pemain satu) dan P2 (pemain dua). Ini masuk akal untuk gim pertempuran, tetapi juga sesuatu yang bisa Anda manfaatkan untuk meningkatkan logika Anda.
2: 3 ketukan 0 ketukan 2 ketukan 1 ketukan 3. Satu-satunya kasus yang tidak dicakup oleh kasus ini adalah kombinasi dari 0 vs 1 dan 2 vs 3. Dengan kata lain tabel kemenangan yang unik terlihat seperti ini: 0 ketukan 2, 1 ketukan 3, 2 ketukan 1, 3 ketukan 0.
3: Jika 0/1 melawan satu sama lain maka ada hasil imbang tanpa hit tetapi jika 2/3 naik melawan masing-masing maka keduanya memukul
Pertama, mari kita bangun fungsi satu arah untuk memberi tahu kita jika kita menang:
Kami kemudian dapat menggunakan fungsi ini untuk menyusun hasil akhir:
Walaupun ini bisa dibilang lebih kompleks dan mungkin lebih lambat daripada pencarian tabel yang ditawarkan dalam banyak jawaban, saya percaya ini adalah metode yang unggul karena sebenarnya merangkum logika kode Anda dan menjelaskannya kepada siapa pun yang membaca kode Anda. Saya pikir ini membuatnya menjadi implementasi yang lebih baik.
(Sudah lama sejak saya melakukan Java, jadi minta maaf jika sintaks dimatikan, mudah-mudahan masih dapat dimengerti jika saya salah mengerti)
By the way, 0-3 jelas berarti sesuatu; mereka bukan nilai yang sewenang-wenang sehingga akan membantu untuk memberi nama mereka.
sumber
Saya harap saya mengerti logikanya dengan benar. Bagaimana dengan sesuatu seperti:
Memeriksa satu hit tinggi atau satu hit rendah tidak diblokir dan sama untuk pemain dua.
Sunting: Algoritma tidak sepenuhnya dipahami, "hit" diberikan ketika memblokir yang tidak saya sadari (Thx elias):
sumber
Saya tidak punya pengalaman dengan Java jadi mungkin ada beberapa kesalahan ketik. Silakan pertimbangkan kode ini sebagai kode semu.
Saya akan pergi dengan saklar sederhana. Untuk itu, Anda perlu evaluasi nomor tunggal. Namun, untuk kasus ini, karena
0 <= one < 4 <= 9
dan0 <= two < 4 <= 9
, kita dapat mengonversi kedua int menjadi int sederhana dengan mengalikannyaone
dengan 10 dan menambahkantwo
. Kemudian gunakan saklar di nomor yang dihasilkan seperti ini:Ada metode pendek lain yang saya ingin tunjukkan sebagai kode teoritis. Namun saya tidak akan menggunakannya karena memiliki beberapa kompleksitas tambahan yang biasanya tidak ingin Anda tangani. Kompleksitas ekstra berasal dari basis 4 , karena penghitungan adalah 0, 1, 2, 3, 10, 11, 12, 13, 20, ...
Benar-benar hanya catatan tambahan, kalau-kalau saya kehilangan sesuatu dari Jawa. Dalam PHP saya akan melakukan:
sumber
Karena Anda lebih suka bersarang
if
kondisi, inilah cara lain.Perhatikan bahwa itu tidak menggunakan
result
anggota dan itu tidak mengubah keadaan apa pun.sumber
else
rantai tapi itu tidak membuat perbedaan.else if
pernyataan panjang, kita dapat mempercepat kode denganswitch
atau mencari tabel.one==0
akan menjalankan kode, maka harus memeriksa jikaone==1
lalu jikaone==2
dan akhirnya jikaone==3
- Jika ada yang lain di sana, itu tidak akan melakukan tiga pemeriksaan terakhir karena akan keluar dari pernyataan setelah pertandingan pertama. Dan ya, Anda bisa lebih mengoptimalkan dengan menggunakan pernyataan switch di tempatif (one...
pernyataan dan kemudian menggunakan switch lain di dalam kasus inione's
. Namun, itu bukan pertanyaan saya.Cobalah dengan saklar casing. ..
Lihatlah di sini atau di sini untuk info lebih lanjut tentang itu
Anda dapat menambahkan beberapa kondisi (tidak secara bersamaan) dan bahkan memiliki opsi default di mana tidak ada kasus lain telah terpenuhi.
PS: Hanya kalau satu syarat harus dipenuhi ..
Jika 2 kondisi muncul secara bersamaan .. Saya rasa switch tidak dapat digunakan. Tetapi Anda dapat mengurangi kode Anda di sini.
Java beralih pernyataan beberapa kasus
sumber
Hal pertama yang terjadi pada saya pada dasarnya adalah jawaban yang sama yang diberikan oleh Francisco Presencia, tetapi agak dioptimalkan:
Anda dapat lebih mengoptimalkannya dengan menjadikan case terakhir (untuk 3) sebagai case default:
Keuntungan dari metode ini adalah bahwa lebih mudah untuk melihat nilai untuk
one
dantwo
sesuai dengan nilai yang dikembalikan dari beberapa metode lain yang disarankan.sumber
sumber
; --unicorns
Anda dapat menggunakan sakelar alih-alih mutiple
if
Juga menyebutkan bahwa karena Anda memiliki dua variabel maka Anda harus menggabungkan kedua variabel untuk menggunakannya secara bergantian
Periksa pernyataan beralih Java ini untuk menangani dua variabel?
sumber
Saat saya menggambar tabel antara satu / dua dan hasilnya, saya melihat satu pola,
Pernyataan di atas akan mengurangi minimal 3 jika pernyataan. Saya tidak melihat pola yang ditetapkan atau saya bisa mendapatkan banyak dari kode yang diberikan - tetapi jika logika tersebut dapat diturunkan, itu akan mengurangi sejumlah pernyataan if.
Semoga ini membantu.
sumber
Poin yang baik adalah mendefinisikan aturan sebagai teks, Anda dapat dengan mudah mendapatkan rumus yang benar. Ini diekstrak dari representasi array bagus laalto:
Dan di sini kita pergi dengan beberapa komentar umum, tetapi Anda harus menggambarkannya dalam istilah aturan:
Tentu saja Anda bisa memecahnya menjadi lebih sedikit kode, tetapi umumnya merupakan ide bagus untuk memahami kode apa yang Anda miliki daripada mencari solusi yang ringkas.
Beberapa penjelasan tentang hit p1 / p2 yang rumit akan sangat bagus, terlihat menarik!
sumber
Solusi terpendek dan masih dapat dibaca:
atau bahkan lebih pendek:
Tidak mengandung angka "ajaib";) Semoga ini bisa membantu.
sumber
static int val(int i, int u){ int q = (i & 1) ^ (u & 1); return ((i >> 1) << (1 ^ q))|((u >> 1) << q); }
sumber
Secara pribadi saya suka membuat operator ternary:
Tetapi dalam kasus Anda, Anda dapat menggunakan:
Atau, Anda dapat melihat pola dalam bit:
Jadi Anda bisa menggunakan sihir:
sumber
Ini versi yang cukup ringkas, mirip dengan respons JAB . Ini menggunakan peta untuk menyimpan yang bergerak menang atas yang lain.
Contoh:
Cetakan:
sumber
static final Map<Move, List<Move>> beats = new java.util.EnumMap<>();
sebagai gantinya, itu harus sedikit lebih efisien.Saya akan menggunakan Peta, baik HashMap atau TreeMap
Apalagi jika parameternya tidak pada formulir
0 <= X < N
Seperti satu set bilangan bulat positif acak ..
Kode
sumber
Terima kasih kepada @ Jooe Harper karena saya akhirnya menggunakan variasi jawabannya. Untuk menurunkannya lebih jauh karena 2 hasil per 4 adalah sama, saya menurunkannya lebih jauh.
Saya mungkin kembali ke ini di beberapa titik, tetapi jika tidak ada perlawanan besar yang disebabkan oleh beberapa
if
pernyataan maka saya akan menyimpan ini untuk saat ini. Saya akan melihat matriks tabel dan beralih solusi pernyataan lebih lanjut.sumber
Berikut adalah saran bagaimana ini terlihat, tetapi menggunakan int di sini masih agak jelek:
Akan lebih baik untuk menggunakan tipe terstruktur untuk input dan output. Input sebenarnya memiliki dua bidang: posisi dan tipe (blok atau serangan). Outputnya juga memiliki dua bidang: player1Wins dan player2Wins. Pengkodean ini menjadi satu bilangan bulat membuat lebih sulit untuk membaca kode.
Sayangnya, Java tidak terlalu bagus dalam mengekspresikan tipe-tipe data tersebut.
sumber
Alih-alih lakukan sesuatu seperti ini
sumber